diff --git a/.gitignore b/.gitignore index dfcfd56..d2da6d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,3 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - # User-specific files *.rsuser *.suo @@ -10,12 +5,6 @@ *.userosscache *.sln.docstates -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - # Build results [Dd]ebug/ [Dd]ebugPublic/ @@ -31,320 +20,67 @@ bld/ [Ll]og/ [Ll]ogs/ -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - # .NET Core project.lock.json project.fragment.lock.json artifacts/ -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* +.vs/ +.ionide/* +/src/**/bin/* +/src/**/obj/* +/src/**/Properties/* +/src/**/.vs/* +/src**/*.fsproj.user +/Scripts/.Defaults.ps1 +/cli/.Defaults.ps1 +/k8sConfigs/* +*.swp *~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs +/src/OrchestratorFunc/OrchestratorFunc/Properties/PublishProfiles/* +appsettings.Development.json +.fake +.ionide +/Scripts/webAppSettings.json +/Scripts/orchestratorSettings.json +/cli/defaults.json +/.vscode/* +/.venv/* -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk +/packages +/TestResults -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ +/tools/NuGet.exe +/App_Data +/secrets +/data +.secrets +local.settings.json -# RIA/Silverlight projects -Generated_Code/ +node_modules +dist -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak +# Local python packages +.python_packages/ -# SQL Server files -*.mdf -*.ldf -*.ndf +# Python Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) +# Byte-compiled / optimized / DLL files __pycache__/ -*.pyc +*.py[cod] +*$py.class +/cli/.cache/* +/cli/.vscode/* +/cli/.vscode/* +/cli/raft_sdk/.cache/token_cache.bin -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config +/cli/raft-utils/auth/dotnet-core-3.1/* -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ +/cli/defaults-*.json diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c282e9a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,14 @@ +# Contributing + +This project welcomes contributions and suggestions. Most contributions require you to +agree to a Contributor License Agreement (CLA) declaring that you have the right to, +and actually do, grant us the rights to use your contribution. For details, visit +https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need +to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the +instructions provided by the bot. You will only need to do this once across all repositories using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. \ No newline at end of file diff --git a/GeoPol.xml b/GeoPol.xml new file mode 100644 index 0000000..bc2a470 --- /dev/null +++ b/GeoPol.xml @@ -0,0 +1,23 @@ + + + + + +]> + + + +&GitRepoName; + + + + . + + + + + .gitignore + GeoPol.xml + + diff --git a/LICENSE b/LICENSE.txt similarity index 100% rename from LICENSE rename to LICENSE.txt diff --git a/NOTICE.md b/NOTICE.md new file mode 100644 index 0000000..f21fcd4 --- /dev/null +++ b/NOTICE.md @@ -0,0 +1,10859 @@ +## Use of 3rd Party OSS + +NOTICES AND INFORMATION +Do Not Translate or Localize + +This software incorporates material from third parties. +Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, +or you may send a check or money order for US $5.00, including the product name, +the open source component name, platform, and version number, to: + +Source Code Compliance Team +Microsoft Corporation +One Microsoft Way +Redmond, WA 98052 +USA + +Notwithstanding any other terms, you may reverse engineer this software to the extent +required to debug changes to any libraries licensed under the GNU Lesser General Public License. + +--------------------------------------------------------- + +Castle.Core 4.4.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +Copyright 2004-2016 Castle Project +Copyright (c) 2004-2019 Castle Project +GCopyright (c) 2004-2019 Castle Project + +Copyright 2004-2016 Castle Project - http://www.castleproject.org/ + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Authentication.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Authentication.AzureAD.UI 3.1.8 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation. +Copyright (c) 2014-2018 Michael Daines +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2010-2019 Google LLC. http://angular.io/license + + + + + + + 'Apache-2.0' reference + + +
+ + + +

SPDX identifier

+

Apache-2.0

+ +

License text

+
 Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      
+
+      "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+      
+
+      "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+      
+
+      "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+      
+
+      "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+      
+
+      "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+      
+
+      "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+      
+
+      "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+      
+
+      "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+      
+
+      "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+      
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+      (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright _____
+
+Licensed under the Apache License, Version 2.0 (the "License");
+
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+
+distributed under the License is distributed on an "AS IS" BASIS,
+
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+
+limitations under the License.
+ 
+ + +
+ + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Authentication.Core 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Authentication.JwtBearer 3.1.8 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Authentication.OpenIdConnect 3.1.8 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Andrew Arnott +Copyright (c) 2017 Yoshifumi Kawai +Copyright (c) Microsoft Corporation. +Copyright (c) 2014-2018 Michael Daines +Copyright (c) 2013-2017, Milosz Krajewski +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2010-2019 Google LLC. http://angular.io/license + + + + + + + 'Apache-2.0' reference + + +
+ + + +

SPDX identifier

+

Apache-2.0

+ +

License text

+
 Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      
+
+      "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+      
+
+      "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+      
+
+      "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+      
+
+      "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+      
+
+      "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+      
+
+      "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+      
+
+      "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+      
+
+      "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+      
+
+      "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+      
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+      (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright _____
+
+Licensed under the Apache License, Version 2.0 (the "License");
+
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+
+distributed under the License is distributed on an "AS IS" BASIS,
+
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+
+limitations under the License.
+ 
+ + +
+ + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Authorization 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Authorization.Policy 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Hosting.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Hosting.Server.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Http 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Http.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Http.Extensions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Http.Features 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.JsonPatch 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.JsonPatch 3.0.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Mvc.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Mvc.Core 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Mvc.Formatters.Json 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Mvc.NewtonsoftJson 3.0.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Mvc.WebApiCompatShim 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.ResponseCaching.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Routing 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.Routing.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.AspNetCore.WebUtilities 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.ApiDescription.Server 3.0.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright James Newton-King 2008 + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Configuration 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Configuration 3.1.8 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Configuration.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Configuration.Abstractions 3.1.8 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Configuration.Binder 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Configuration.Binder 3.1.8 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Configuration.EnvironmentVariables 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Configuration.FileExtensions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Configuration.Json 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.DependencyInjection 3.1.8 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + + + + + + + 'Apache-2.0' reference + + +
+ + + +

SPDX identifier

+

Apache-2.0

+ +

License text

+
 Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      
+
+      "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+      
+
+      "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+      
+
+      "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+      
+
+      "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+      
+
+      "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+      
+
+      "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+      
+
+      "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+      
+
+      "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+      
+
+      "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+      
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+      (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright _____
+
+Licensed under the Apache License, Version 2.0 (the "License");
+
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+
+distributed under the License is distributed on an "AS IS" BASIS,
+
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+
+limitations under the License.
+ 
+ + +
+ + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.DependencyInjection 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.DependencyInjection.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.DependencyInjection.Abstractions 3.1.8 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.FileProviders.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.FileProviders.Physical 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.FileSystemGlobbing 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Hosting 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Hosting.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Logging 3.1.8 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + + + + + + + 'Apache-2.0' reference + + +
+ + + +

SPDX identifier

+

Apache-2.0

+ +

License text

+
 Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      
+
+      "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+      
+
+      "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+      
+
+      "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+      
+
+      "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+      
+
+      "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+      
+
+      "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+      
+
+      "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+      
+
+      "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+      
+
+      "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+      
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+      (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright _____
+
+Licensed under the Apache License, Version 2.0 (the "License");
+
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+
+distributed under the License is distributed on an "AS IS" BASIS,
+
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+
+limitations under the License.
+ 
+ + +
+ + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Logging 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Logging.Abstractions 3.1.8 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + + + + + + + 'Apache-2.0' reference + + +
+ + + +

SPDX identifier

+

Apache-2.0

+ +

License text

+
 Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      
+
+      "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+      
+
+      "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+      
+
+      "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+      
+
+      "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+      
+
+      "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+      
+
+      "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+      
+
+      "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+      
+
+      "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+      
+
+      "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+      
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+      (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright _____
+
+Licensed under the Apache License, Version 2.0 (the "License");
+
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+
+distributed under the License is distributed on an "AS IS" BASIS,
+
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+
+limitations under the License.
+ 
+ + +
+ + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Logging.Abstractions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Logging.Configuration 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Logging.Configuration 3.1.8 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Logging.Console 3.1.8 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Logging.Debug 3.1.8 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + + + + + + + 'Apache-2.0' reference + + +
+ + + +

SPDX identifier

+

Apache-2.0

+ +

License text

+
 Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      
+
+      "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+      
+
+      "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+      
+
+      "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+      
+
+      "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+      
+
+      "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+      
+
+      "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+      
+
+      "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+      
+
+      "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+      
+
+      "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+      
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+      (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright _____
+
+Licensed under the Apache License, Version 2.0 (the "License");
+
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+
+distributed under the License is distributed on an "AS IS" BASIS,
+
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+
+limitations under the License.
+ 
+ + +
+ + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.ObjectPool 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Options 3.1.8 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + + + + + + + 'Apache-2.0' reference + + +
+ + + +

SPDX identifier

+

Apache-2.0

+ +

License text

+
 Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      
+
+      "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+      
+
+      "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+      
+
+      "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+      
+
+      "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+      
+
+      "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+      
+
+      "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+      
+
+      "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+      
+
+      "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+      
+
+      "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+      
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+      (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright _____
+
+Licensed under the Apache License, Version 2.0 (the "License");
+
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+
+distributed under the License is distributed on an "AS IS" BASIS,
+
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+
+limitations under the License.
+ 
+ + +
+ + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Options 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Options.ConfigurationExtensions 3.1.8 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + + + + + + + 'Apache-2.0' reference + + +
+ + + +

SPDX identifier

+

Apache-2.0

+ +

License text

+
 Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      
+
+      "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+      
+
+      "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+      
+
+      "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+      
+
+      "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+      
+
+      "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+      
+
+      "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+      
+
+      "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+      
+
+      "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+      
+
+      "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+      
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+      (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright _____
+
+Licensed under the Apache License, Version 2.0 (the "License");
+
+you may not use this file except in compliance with the License.
+
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+
+distributed under the License is distributed on an "AS IS" BASIS,
+
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
+See the License for the specific language governing permissions and
+
+limitations under the License.
+ 
+ + +
+ + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Options.ConfigurationExtensions 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Primitives 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Primitives 3.1.8 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Net.Http.Headers 2.1.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +ncrontab.signed 3.3.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +Copyright 2008, Atif Aziz. +zCopyright 2008, Atif Aziz. +Copyright (c) 2008 Atif Aziz. +Copyright (c) 2001 The OpenSymphony Group. +Portions Copyright 2001 The OpenSymphony Group. +Portions Copyright (c) 2001 The OpenSymphony Group. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + +--------------------------------------------------------- + +--------------------------------------------------------- + +NuGet.Frameworks 5.0.0 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +WindowsAzure.Storage 9.3.3 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright 2018 Microsoft Corp. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +xunit 2.4.1 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +xunit.abstractions 2.0.3 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +Copyright (c) Outercurve Foundation +Copyright (c) Outercurve Foundation WrapNonExceptionThrows RSDS + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +xunit.analyzers 0.10.0 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +xunit.assert 2.4.1 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +Copyright (c) .NET Foundation +Copyright (c) .NET Foundation xUnit.net Assertion Library + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +xunit.core 2.4.1 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +xunit.extensibility.core 2.4.1 - Apache-2.0 + + +(c) 2008 VeriSign, Inc. +Copyright (c) .NET Foundation +Copyright (c) .NET Foundation xUnit.net +Copyright (c) .NET Foundation 0xUnit.net +Copyright (c) .NET Foundation xUnit.net Runner Utility + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +xunit.extensibility.execution 2.4.1 - Apache-2.0 + + + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +--------------------------------------------------------- + +--------------------------------------------------------- + +NSubstitute 4.2.2 - BSD-3-Clause + + +(c) 2008 VeriSign, Inc. + +Copyright (c) . All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Azure.Core 1.5.0 - MIT + + + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Azure.Storage.Common 12.5.2 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Azure.Storage.Files.Shares 12.4.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +coverlet.collector 1.3.0 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright 2008 - 2018 Jb Evain +Copyright Microsoft Corporation +Copyright James Newton-King 2008 + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +FSharp.Core 4.7.2 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.ApplicationInsights 2.14.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.ApplicationInsights.AspNetCore 2.14.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.ApplicationInsights.DependencyCollector 2.14.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.ApplicationInsights.EventCounterCollector 2.14.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.ApplicationInsights.PerfCounterCollector 2.14.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.ApplicationInsights.WindowsServer 2.14.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel 2.14.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Cosmos.Table 1.0.8 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2015 Microsoft + +The MIT License (MIT) + +Copyright (c) 2015 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.EventGrid 3.2.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.KeyVault 3.0.1 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Microsoft Corporation + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.KeyVault.Core 2.0.4 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright (c) Microsoft Corporation + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.KeyVault.WebKey 3.0.1 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Microsoft Corporation + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.AppService.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.BatchAI.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Cdn.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Compute.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.ContainerInstance.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.ContainerRegistry 5.0.0-preview.3 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft +Copyright (c) Microsoft Corporation + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.ContainerRegistry.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.ContainerService.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.CosmosDB.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Dns.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.EventGrid 6.0.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft +Copyright (c) Microsoft Corporation + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.EventHub.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Graph.RBAC.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.KeyVault.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Locks.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Monitor.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Msi.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Network.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.PrivateDns.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Redis.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.ResourceManager.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Search.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.ServiceBus.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Sql.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.Storage.Fluent 1.34.0 - MIT + + +Create (c), Update +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Management.TrafficManager.Fluent 1.34.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2019 Microsoft + +The MIT License (MIT) + +Copyright (c) 2019 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.ServiceBus 5.0.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Services.AppAuthentication 1.0.3 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Microsoft Corporation. +9Copyright (c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Azure.Storage.Common 11.2.2 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright 2019 Microsoft Corp. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Bcl.AsyncInterfaces 1.0.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.DotNet.PlatformAbstractions 2.1.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2015 .NET Foundation +Copyright (c) Microsoft Corporation +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 1991-2017 Unicode, Inc. +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To + +The MIT License (MIT) + +Copyright (c) 2015 .NET Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.DependencyModel 2.1.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2011, Google Inc. +Copyright (c) 1998 Microsoft. To +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2015 .NET Foundation +Copyright (c) Microsoft Corporation +Copyright (c) 2012-2014, Yann Collet +Copyright (c) 1991-2017 Unicode, Inc. +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) The Internet Society 1997. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) .NET Foundation Contributors +Copyright (c) The Internet Society (2003). +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com +Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. +Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To + +The MIT License (MIT) + +Copyright (c) 2015 .NET Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Extensions.Logging.ApplicationInsights 2.14.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Identity.Client 4.18.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Clients.ActiveDirectory 3.14.2 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright (c) Microsoft Corporation. +9Copyright (c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Clients.ActiveDirectory 4.3.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Clients.ActiveDirectory 5.2.8 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Microsoft Corporation + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.JsonWebTokens 5.4.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.JsonWebTokens 5.5.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Logging 1.1.2 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright (c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Logging 5.4.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Logging 5.5.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Protocols 5.5.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Protocols.OpenIdConnect 5.5.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Tokens 5.5.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Tokens 5.4.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.IdentityModel.Tokens 5.1.2 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright (c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.NET.Sdk.Functions 3.0.9 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright 2008 - 2018 Jb Evain +Copyright James Newton-King 2008 + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.OData.Edm 7.6.4 - MIT + + +Copyright (c) OASIS +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2018 Microsoft. +Copyright (c) Microsoft Corporation. +9Copyright (c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Rest.ClientRuntime 2.3.19 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Microsoft Corporation + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Rest.ClientRuntime 2.3.20 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Microsoft Corporation + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Rest.ClientRuntime.Azure 3.3.19 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Microsoft Corporation + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Rest.ClientRuntime.Azure 3.3.18 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Microsoft Corporation + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Rest.ClientRuntime.Azure.Authentication 2.4.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) Microsoft Corporation + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Microsoft.Win32.SystemEvents 4.7.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Newtonsoft.Json 10.0.3 - MIT + + +Copyright (c) 2007 James Newton-King + +The MIT License (MIT) + +Copyright (c) 2007 James Newton-King + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Newtonsoft.Json 11.0.2 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright James Newton-King 2008 +Copyright (c) 2007 James Newton-King +Copyright (c) James Newton-King 2008 + +The MIT License (MIT) + +Copyright (c) 2007 James Newton-King + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Newtonsoft.Json 12.0.2 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright James Newton-King 2008 +Copyright (c) 2007 James Newton-King +Copyright (c) James Newton-King 2008 + +The MIT License (MIT) + +Copyright (c) 2007 James Newton-King + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Newtonsoft.Json.Bson 1.0.2 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright James Newton-King 2017 +Copyright (c) 2017 James Newton-King +Copyright (c) James Newton-King 2017 + +The MIT License (MIT) + +Copyright (c) 2017 James Newton-King + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Newtonsoft.Json.Bson 1.0.1 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright James Newton-King 2017 +Copyright (c) James Newton-King 2017 + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Scrutor 3.0.1 - MIT + + + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +Swashbuckle.AspNetCore 5.0.0 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright (c) 2016 Richard Morris + +The MIT License (MIT) + +Copyright (c) 2016 Richard Morris + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +Swashbuckle.AspNetCore.Filters 5.1.2 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright (c) 2017 Matt Frear + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Configuration.ConfigurationManager 4.7.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Diagnostics.PerformanceCounter 4.7.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Drawing.Common 4.7.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.IdentityModel.Tokens.Jwt 5.4.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.IdentityModel.Tokens.Jwt 5.5.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.IO.FileSystem.AccessControl 4.7.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Memory 4.5.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 1991-2017 Unicode, Inc. +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Memory 4.5.4 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 1991-2017 Unicode, Inc. +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Runtime.CompilerServices.Unsafe 4.5.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 1991-2017 Unicode, Inc. +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Security.AccessControl 4.7.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Security.Cryptography.ProtectedData 4.7.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Security.Permissions 4.7.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Text.Encodings.Web 4.5.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 1991-2017 Unicode, Inc. +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Text.Json 4.6.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.ValueTuple 4.4.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 1991-2017 Unicode, Inc. +Portions (c) International Organization +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +System.Windows.Extensions 4.7.0 - MIT + + +(c) 2008 VeriSign, Inc. +(c) Microsoft Corporation. +Copyright (c) .NET Foundation. +Copyright (c) 2011, Google Inc. +(c) 1997-2005 Sean Eron Anderson. +Copyright (c) 2007 James Newton-King +Copyright (c) 1991-2017 Unicode, Inc. +Copyright (c) 2013-2017, Alfred Klomp +Copyright (c) 2015-2017, Wojciech Mula +Copyright (c) 2005-2007, Nick Galbreath +Portions (c) International Organization +Copyright (c) 2015 The Chromium Authors. +Copyright (c) 2004-2006 Intel Corporation +Copyright (c) 2016-2017, Matthieu Darbois +Copyright (c) .NET Foundation Contributors +Copyright (c) .NET Foundation and Contributors +Copyright (c) 2011 Novell, Inc (http://www.novell.com) +Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +xunit.runner.visualstudio 2.4.3 - MIT + + +(c) 2008 VeriSign, Inc. +Copyright (c) .NET Foundation +Copyright (c) 2015 .NET Foundation +Copyright (c) Outercurve Foundation +Copyright (c) .NET Foundation and Contributors. +Copyright (c) .NET Foundation xUnit.net Runner Utility +Copyright (c) .NET Foundation ,xUnit.net Runner Utility +Copyright (c) .NET Foundation 1xUnit.net Runner Utility +Copyright (c) .NET Foundation xUnit.net Runner Reporters +Copyright (c) .NET Foundation .xUnit.net Runner Reporters +Copyright (c) Outercurve Foundation WrapNonExceptionThrows RSDS +Copyright (c) .NET Foundation and Contributors. Visual Studio 2017 15.9+ Test Explorer + +Unless otherwise noted, the source code here is covered by the following license: + + Copyright (c) .NET Foundation and Contributors + All Rights Reserved + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +----------------------- + +The code in src/xunit.runner.visualstudio/Utility/AssemblyResolution/Microsoft.DotNet.PlatformAbstractions was imported from: + https://github.com/dotnet/core-setup/tree/v2.0.1/src/managed/Microsoft.DotNet.PlatformAbstractions + +The code in src/xunit.runner.visualstudio/Utility/AssemblyResolution/Microsoft.DotNet.PlatformAbstractions was imported from: + https://github.com/dotnet/core-setup/tree/v2.0.1/src/managed/Microsoft.Extensions.DependencyModel + +Both sets of code are covered by the following license: + + The MIT License (MIT) + + Copyright (c) 2015 .NET Foundation + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + +--------------------------------------------------------- + diff --git a/PRIVACY.md b/PRIVACY.md new file mode 100644 index 0000000..b0bc9c4 --- /dev/null +++ b/PRIVACY.md @@ -0,0 +1,2 @@ +## Data Collection. +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft's privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/README.md b/README.md index 8eeee9c..ecdcfc7 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,40 @@ +# REST API Fuzz Testing (RAFT) -# Contributing +## A self hosted REST API Fuzzing-As-A-Service platform +RAFT enables painless fuzzing of REST API's using multiple fuzzers in parallel. Using a single command line +baked into your CI/CD pipeline developers can launch fuzz jobs against their services. + +RAFT has first class integration with Microsoft's Research's [RESTler](https://github.com/microsoft/restler), the first stateful, +fuzzing tool designed to automatically test your REST API's driven by your swagger specification. -This project welcomes contributions and suggestions. Most contributions require you to agree to a -Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. +RAFT also supports [ZAP](https://www.zaproxy.org/) from OWASP out of the box. -When you submit a pull request, a CLA bot will automatically determine whether you need to provide -a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions -provided by the bot. You will only need to do this once across all repos using our CLA. +As a platform, RAFT is designed to host any API fuzzers that are packaged into a docker container. +These can be configured and used in the system via configuration files and require no code changes to integrate. -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +### Getting Started +This project is designed to run on [Azure](https://azure.microsoft.com). + +To deploy the service download the CLI release and run `python raft.py service deploy`. See +the [documentation](docs/deploying/deploying.md) for more details. + +Once deployed, use the samples to try out the service and fuzzers! + +### Documentation + +* [Table of Contents](docs/index.md) +* [Overview](docs/how-it-works/overview.md) +* [FAQ](docs/faq.md) + +### Swagger Documentation +Once the service is created, you can examine the REST interface of the service by browsing to the swagger page at https://\-raft-apiservice.azurewebsites.net/swagger + +### Microsoft Open Source Code of Conduct +https://opensource.microsoft.com/codeofconduct + +### Trademarks +Trademarks This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies. + +### Preferred Languages + +We prefer all communications to be in English. diff --git a/Scripts/Tests/bvt.py b/Scripts/Tests/bvt.py new file mode 100644 index 0000000..8d9ac87 --- /dev/null +++ b/Scripts/Tests/bvt.py @@ -0,0 +1,186 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import argparse +import json +import os +import pathlib +import sys +import requests +import time + +cli_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),'..', '..', 'cli') +sys.path.append(cli_path) +import raft +from raft_sdk.raft_service import RaftCLI +from raft_sdk.raft_common import RaftDefinitions +from raft_sdk.raft_deploy import azure_function_keys + +def webhooks_test_url(subscription_id, resource_group, function): + keys = azure_function_keys(subscription_id, resource_group, function, "webhooks-trigger-test") + return f"https://{function}.azurewebsites.net/api/test?{keys['default']}" + +def webhook_triggers_results(job_id, test_url): + webhook_triggers_response = requests.get(test_url + "&jobId=" + job_id) + if webhook_triggers_response.ok: + triggers = json.loads(webhook_triggers_response.text) + for t in triggers: + j = json.loads(t) + yield j[0] + else: + raise Exception(webhook_triggers_response.text) + +def time_span(t_start, t_end): + return time.strftime("%H:%M:%S", time.gmtime(t_end - t_start)) + +def bvt(cli, definitions, bvt_host): + print('Getting available wehook events') + webhook_events = cli.list_available_webhooks_events() + try: + test_url = webhooks_test_url(definitions.subscription, definitions.resource_group, definitions.test_infra) + for event in webhook_events: + print(f'Setting webhook for {event}') + compile_webhook = cli.set_webhooks_subscription('sample-compile', event, test_url) + fuzz_webhook = cli.set_webhooks_subscription('sample-fuzz', event, test_url) + + added_compile = cli.list_webhooks('sample-compile', event) + if len(added_compile) == 0: + raise Exception('Expected sample-compile webhooks not to be empty after creation') + + added_fuzz = cli.list_webhooks('sample-fuzz', event) + if len(added_fuzz) == 0: + raise Exception('Expected sample-fuzz webhooks not to be empty after creation') + + t_pre_compile = time.time() + + print('Compile') + compile_config_path = os.path.abspath(os.path.join(cli_path, 'samples', 'no-authentication-sample', 'sample.restler.compile.json')) + subs = { + '{sample.host}' : bvt_host + } + compile_config = raft.RaftJobConfig(file_path=compile_config_path, substitutions=subs) + compile_job = cli.new_job(compile_config) + cli.poll(compile_job['jobId'], 10) + + #calculate compile duration + t_pre_fuzz = time.time() + timespan_pre_fuzz = time_span(t_pre_compile, t_pre_fuzz) + after_compile_pre_fuzz = cli.list_jobs(timespan_pre_fuzz) + + n = 0 + for x in after_compile_pre_fuzz: + if x['jobId'] == compile_job['jobId']: + n += 1 + if x['agentName'] == compile_job['jobId']: + if x['state'] != 'Completed': + raise Exception('Expected job to be in completed state when retrieved job list.' + f'{after_compile_pre_fuzz}') + + if n != 3: + raise Exception('Expected 3 after compile job step' + f' for job {compile_job["jobId"]}' + f' got {n}' + f' {after_compile_pre_fuzz}') + + print('Fuzz') + fuzz_config_path = os.path.abspath(os.path.join(cli_path, 'samples', 'no-authentication-sample', 'sample.restler.fuzz.json')) + subs['{compile.jobId}'] = compile_job['jobId'] + fuzz_config = raft.RaftJobConfig(file_path=fuzz_config_path, substitutions=subs) + fuzz_config.config['duration'] = '00:20:00' + fuzz_job = cli.new_job(fuzz_config) + cli.poll(fuzz_job['jobId'], 10) + + #calculate fuzz duration + timespan_post_fuzz = time_span(t_pre_fuzz, time.time()) + after_fuzz = cli.list_jobs(timespan_post_fuzz) + + #validate list jobs + m = 0 + for x in after_fuzz: + if x['jobId'] == fuzz_job['jobId']: + m += 1 + + if x['agentName'] == fuzz_job['jobId']: + if x['state'] != 'Completed': + raise Exception('Expected job to be in completed state when retrieved job list.' + f'{after_fuzz}') + + if m != 4: + raise Exception('Expected 4 after compile job step' + f' for job {fuzz_job["jobId"]}' + f' got {m}' + f' {after_fuzz}') + + + print('Validating webhook posted triggers') + compile_webhook_triggers = webhook_triggers_results(compile_job['jobId'], test_url) + for r in compile_webhook_triggers: + if r['EventType'] == 'BugFound': + raise Exception(f'Compile step produced BugFound event') + + fuzz_webhook_triggers = webhook_triggers_results(fuzz_job['jobId'], test_url) + + bug_found_events = [] + job_status_events = [] + + for r in fuzz_webhook_triggers: + if r['EventType'] == 'BugFound': + bug_found_events.append(r) + elif r['EventType'] == 'JobStatus': + job_status_events.append(r) + else: + raise Exception(f'Unhandled webhook trigger event type {r["EventType"]} : {r}') + + if len(job_status_events) == 0: + raise Exception('Job did not post any job status events webhooks') + + print('Validating that bugs posted events matches total bugs found in job status') + total_bugs_found = 0 + for r in job_status_events: + if r['Data']['State'] == 'Completed' and r['Data']['AgentName'] != r['Data']['JobId']: + total_bugs_found += r['Data']['Metrics']['TotalBugBucketsCount'] + + print(f'Total bugs found: {total_bugs_found}') + print(f'Number of Bug found events: {len(bug_found_events)}') + if total_bugs_found != len(bug_found_events): + raise Exception(f"Total bugs found does not match number of bug found webhook triggered events {total_bugs_found} and {len(bug_found_events)}") + + except Exception as ex: + print(f"FAIL: {ex}") + raise ex + finally: + for event in webhook_events: + print(f'Cleaning up webhook {event}') + cli.delete_webhook('sample-compile', event) + cli.delete_webhook('sample-fuzz', event) + + deleted_compile = cli.list_webhooks('sample-compile', event) + if len(deleted_compile) > 0: + raise Exception('Expected sample-compile webhooks to be empty after deletion, instead got %s', deleted_compile) + + deleted_fuzz = cli.list_webhooks('sample-fuzz', event) + if len(deleted_fuzz) > 0: + raise Exception('Expected sample-fuzz webhooks to be empty after deletion, instead got %s', deleted_compile) + + + +if __name__ == "__main__": + formatter = argparse.ArgumentDefaultsHelpFormatter + parser = argparse.ArgumentParser(description='bvt', formatter_class=formatter) + raft.add_defaults_and_secret_args(parser) + + parser.add_argument('--host', required=True) + + args = parser.parse_args() + + if args.defaults_context_json: + print(f"Loading defaults from command line: {args.defaults_context_json}") + defaults = json.loads(args.defaults_context_json) + else: + with open(args.defaults_context_path, 'r') as defaults_json: + defaults = json.load(defaults_json) + + definitions = RaftDefinitions(defaults) + defaults['secret'] = args.secret + cli = RaftCLI(defaults) + bvt(cli, definitions, args.host) \ No newline at end of file diff --git a/Scripts/Tests/list-available-webhook-events.py b/Scripts/Tests/list-available-webhook-events.py new file mode 100644 index 0000000..5f672cd --- /dev/null +++ b/Scripts/Tests/list-available-webhook-events.py @@ -0,0 +1,37 @@ +import argparse +import json +import os +import pathlib +import sys +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)),'..', '..', 'cli')) +import raft +from raft_sdk.raft_service import RaftCLI + + +def compare_lists(cli): + expected = ['JobStatus', 'BugFound'] + + current = cli.list_available_webhooks_events() + + if expected != current: + raise Exception(f'Expected {expected} does not match current {current}') + else: + print('PASS') + +if __name__ == "__main__": + formatter = argparse.ArgumentDefaultsHelpFormatter + parser = argparse.ArgumentParser(description = 'List webhooks', formatter_class=formatter) + raft.add_defaults_and_secret_args(parser) + + args = parser.parse_args() + + if args.defaults_context_json: + print(f"Loading defaults from command line: {args.defaults_context_json}") + defaults = json.loads(args.defaults_context_json) + else: + with open(args.defaults_context_path, 'r') as defaults_json: + defaults = json.load(defaults_json) + + defaults['secret'] = args.secret + cli = RaftCLI(defaults) + compare_lists(cli) \ No newline at end of file diff --git a/ado/build-publish-deploy-test.yml b/ado/build-publish-deploy-test.yml new file mode 100644 index 0000000..d0545cf --- /dev/null +++ b/ado/build-publish-deploy-test.yml @@ -0,0 +1,35 @@ +trigger: + batch : true + branches: + include: + - '*' + +parameters: + - name: variable_group + displayName: Variable Group + default: "" + + - name: RunBvt + displayName: Run BVT? + default: Yes + values: + - Yes + - No + +variables: + - template: 'variables/version-variables.yml' + - group: ${{ parameters.variable_group }} + - name: version.revision + value: $[counter(variables['devRevision'], 1)] + - name: versionNumber + value: $(version.major).$(version.minor).$(version.revision) + +stages: + - template: stages/build/build.yml + - template: stages/publish/publish.yml + parameters: + variable_group: ${{ parameters.variable_group }} + - template: stages/deploy/deploy.yml + - template: stages/test/test.yml + parameters: + RunBvt: ${{ parameters.RunBvt }} diff --git a/ado/build.security.yml b/ado/build.security.yml new file mode 100644 index 0000000..7d9d462 --- /dev/null +++ b/ado/build.security.yml @@ -0,0 +1,94 @@ +# Some of these tasks will only run on a windows build machine. +# A number of variables need to be defined for this pipeline to work correctly. +# +# BuildConfiguration | Debug +# BuildPlatform | Any CPU +# isSecurityBuild | True + +pool: + name: Azure Pipelines + demands: + - msbuild + - visualstudio + vmImage: 'windows-2019' + +jobs: +- job: RaftSecurityBuild + displayName: 'RAFT Security build' + + steps: + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet 5.4' + inputs: + versionSpec: 5.4 + + - task: NuGetCommand@2 + displayName: 'Restore NuGet Packages' + inputs: + restoreSolution: src\Raft.sln + + - task: VSBuild@1 + displayName: 'Build solution src\Raft.sln' + inputs: + solution: src\Raft.sln + platform: '$(BuildPlatform)' + configuration: '$(BuildConfiguration)' + + - task: CopyFiles@2 + displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: '**\bin\$(BuildConfiguration)\**' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: 'Component Detection' + + - task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@3 + displayName: 'Run BinSkim' + inputs: + InputType: Basic + AnalyzeTarget: '$(Build.ArtifactStagingDirectory)\*.exe;$(Build.ArtifactStagingDirectory)\*.dll' + AnalyzeVerbose: true + AnalyzeStatistics: true + AnalyzeEnvironment: true + enabled: false + + - task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@2 + displayName: 'Run CredScan' + inputs: + outputFormat: sarif + debugMode: false + continueOnError: true + + - task: securedevelopmentteam.vss-secure-development-tools.build-task-roslynanalyzers.RoslynAnalyzers@2 + displayName: 'Run Roslyn Analyzers' + + - task: securedevelopmentteam.vss-secure-development-tools.build-task-vulnerabilityassessment.VulnerabilityAssessment@0 + displayName: 'Run Vulnerability Assessment' + + - task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@2 + condition: and(succeeded(), eq(variables['isSecurityBuild'], 'True')) + displayName: 'Publish Security Analysis Logs' + + # For this task there needs to be a pipeline variable `System.AccessToken` + # This is a Personal Access Token. These do not have unlimited lifetimes. + # The current token expires at the end + # of March 2021. + - task: corygehr.air-autoassess.uploadScanResults.uploadScanResults@1 + condition: and(succeeded(), eq(variables['isSecurityBuild'], 'True')) + displayName: 'Upload Scan Results for Analysis' + inputs: + areaPathParent: Raft + uploadUrl: 'https://airbuildscan.azurewebsites.net/api/Upload' + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + + - task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@1 + condition: and(succeeded(),eq(variables['isSecurityBuild'], 'True')) + displayName: 'Post Analysis' + inputs: + BinSkim: true + CredScan: true + RoslynAnalyzers: true + \ No newline at end of file diff --git a/ado/production-build.yml b/ado/production-build.yml new file mode 100644 index 0000000..68de8c4 --- /dev/null +++ b/ado/production-build.yml @@ -0,0 +1,13 @@ +trigger: + batch : true + branches: + include: + - 'main' + +variables: + versionNumber: 1.0.0 + imageTag: 'v1.0' + imageTagWithBuildDate: $(imageTag)-$(Build.BuildNumber) + +stages: + - template: stages/build/build.yml \ No newline at end of file diff --git a/ado/pull-request-build-validation.yml b/ado/pull-request-build-validation.yml new file mode 100644 index 0000000..13e672f --- /dev/null +++ b/ado/pull-request-build-validation.yml @@ -0,0 +1,20 @@ +trigger: + batch : true + branches: + include: + - '*' + +variables: + - name: devRevision + value: 1 + - name: version.major + value: 0 + - name: version.minor + value: 7 + - name: version.revision + value: $[counter(variables['devRevision'], 1)] + - name: versionNumber + value: $(version.major).$(version.minor).$(version.revision) + +stages: + - template: stages/build/build.yml diff --git a/ado/rolling-build-publish-deploy-test.yml b/ado/rolling-build-publish-deploy-test.yml new file mode 100644 index 0000000..105cecf --- /dev/null +++ b/ado/rolling-build-publish-deploy-test.yml @@ -0,0 +1,36 @@ +trigger: + batch : true + branches: + include: + - '*' + +parameters: + - name: variable_group + displayName: Variable Group + default: rolling + + - name: RunBvt + displayName: Run BVT? + default: Yes + values: + - Yes + - No + +variables: + - template: 'variables/version-variables.yml' + - group: ${{ parameters.variable_group }} + - name: version.revision + value: $[counter(variables['devRevision'], 1)] + - name: versionNumber + value: $(version.major).$(version.minor).$(version.revision) + +stages: + - template: stages/build/build.yml + - template: stages/publish/publish.yml + parameters: + variable_group: ${{ parameters.variable_group }} + - template: stages/deploy/deploy-infrastructure.yml + - template: stages/deploy/deploy.yml + - template: stages/test/test.yml + parameters: + RunBvt: ${{ parameters.RunBvt }} diff --git a/ado/stages/build/build.yml b/ado/stages/build/build.yml new file mode 100644 index 0000000..c2c1358 --- /dev/null +++ b/ado/stages/build/build.yml @@ -0,0 +1,45 @@ +stages: + - stage: Build + jobs: + - job: CLI + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/cli.yml + + - job: ApiService + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/apiservice.yml + + - job: RESTlerAgent + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/restleragent.yml + + - job: Orchestrator + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/orchestrator.yml + + - job: TestInfra + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/test-infra.yml + + - job: ResultAnalyzer + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/result-analyzer.yml + + - job: AzureAuthUtility + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/azure-auth-utility.yml + \ No newline at end of file diff --git a/ado/stages/build/steps/apiservice.yml b/ado/stages/build/steps/apiservice.yml new file mode 100644 index 0000000..898d612 --- /dev/null +++ b/ado/stages/build/steps/apiservice.yml @@ -0,0 +1,46 @@ +# see https://docs.microsoft.com/en-us/dotnet/core/rid-catalog for definitions of the '-r' flag +steps: + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet 5.4' + inputs: + versionSpec: 5.4 + + - task: NuGetCommand@2 + displayName: 'NuGet restore' + inputs: + restoreSolution: '**\APIService.sln' + + - task: DotNetCoreCLI@2 + displayName: 'APIService' + inputs: + command: publish + publishWebProjects: false + projects: src/APIService/ApiService/APIService.fsproj + arguments: '-c release -r linux-musl-x64 /p:version=$(versionNumber)' + zipAfterPublish: false + + + - task: DotNetCoreCLI@2 + displayName: 'Run Unit Tests : APIService' + inputs: + command: test + projects: src/APIService/ApiService/APIServiceTests/APIServiceTests.fsproj + arguments: -v:detailed + + # Because we are using a a release pipeline we need to publish the Dockerfile + # in the artifacts, since the release pipeline does not have access to the code tree. + - task: CopyFiles@2 + displayName: 'Copy APIService Dockerfile' + inputs: + targetFolder: src/APIService/ApiService/bin/release/netcoreapp3.1/linux-musl-x64/publish/ + sourceFolder: src/APIService/ApiService + contents: Dockerfile + + # Create files with version information that will be used in the release pipeline + - script: echo $(imageTag) > src/APIService/ApiService/bin/release/netcoreapp3.1/linux-musl-x64/publish/imageTag.txt + - script: echo $(imageTagWithBuildDate) > src/APIService/ApiService/bin/release/netcoreapp3.1/linux-musl-x64/publish/imageTagWithBuildDate.txt + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: src/APIService/ApiService/bin/release/netcoreapp3.1/linux-musl-x64/publish + artifactName: apiservice diff --git a/ado/stages/build/steps/azure-auth-utility.yml b/ado/stages/build/steps/azure-auth-utility.yml new file mode 100644 index 0000000..83fa002 --- /dev/null +++ b/ado/stages/build/steps/azure-auth-utility.yml @@ -0,0 +1,24 @@ +steps: + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet 5.4' + inputs: + versionSpec: 5.4 + + - task: NuGetCommand@2 + displayName: 'NuGet restore' + inputs: + restoreSolution: '**\RESTlerAgent.sln' + + - task: DotNetCoreCLI@2 + displayName: 'Azure Auth utility' + inputs: + command: publish + publishWebProjects: false + projects: src/Agent/AzureAuth/AzureAuth.fsproj + arguments: '-c release /p:version=$(versionNumber)' + zipAfterPublish: false + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: src/Agent/AzureAuth/bin/release/netcoreapp3.1/publish/ + artifactName: AzureAuth diff --git a/ado/stages/build/steps/cli.yml b/ado/stages/build/steps/cli.yml new file mode 100644 index 0000000..e3ba906 --- /dev/null +++ b/ado/stages/build/steps/cli.yml @@ -0,0 +1,15 @@ +steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.8' + addToPath: true + + - script: | + pip install pycodestyle + pycodestyle cli/raft.py + displayName: 'Run pycodestyle' + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: cli + artifactName: cli \ No newline at end of file diff --git a/ado/stages/build/steps/orchestrator.yml b/ado/stages/build/steps/orchestrator.yml new file mode 100644 index 0000000..fdc7e96 --- /dev/null +++ b/ado/stages/build/steps/orchestrator.yml @@ -0,0 +1,35 @@ +steps: + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet 5.4' + inputs: + versionSpec: 5.4 + + - task: NuGetCommand@2 + displayName: 'NuGet restore' + inputs: + restoreSolution: '**\Orchestrator.sln' + + - task: DotNetCoreCLI@2 + displayName: 'Orchestrator' + inputs: + command: publish + publishWebProjects: false + projects: src/Orchestrator/Orchestrator/Orchestrator.csproj + arguments: '-c release /p:version=$(versionNumber)' + zipAfterPublish: false + + # Because we are using a deployment job with the orchestrator we need to push the + # Dockerfile in with the artifacts. The deployment job does not check out the source code + # like a normal job. + - task: CopyFiles@2 + displayName: 'Copy Orchestrator Dockerfile' + inputs: + targetFolder: src/Orchestrator/Orchestrator/bin/release/netcoreapp3.1/publish/ + sourceFolder: src/Orchestrator + contents: Dockerfile + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: src/Orchestrator/Orchestrator/bin/release/netcoreapp3.1/publish/ + artifactName: Orchestrator + diff --git a/ado/stages/build/steps/restleragent.yml b/ado/stages/build/steps/restleragent.yml new file mode 100644 index 0000000..140dcd8 --- /dev/null +++ b/ado/stages/build/steps/restleragent.yml @@ -0,0 +1,24 @@ +steps: + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet 5.4' + inputs: + versionSpec: 5.4 + + - task: NuGetCommand@2 + displayName: 'NuGet restore' + inputs: + restoreSolution: '**\RESTlerAgent.sln' + + - task: DotNetCoreCLI@2 + displayName: 'RESTlerAgent' + inputs: + command: publish + publishWebProjects: false + projects: src/Agent/RESTlerAgent/RestlerAgent.fsproj + arguments: '-c release /p:version=$(versionNumber)' + zipAfterPublish: false + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: src/Agent/RESTlerAgent/bin/release/netcoreapp3.1/publish/ + artifactName: RestlerAgent diff --git a/ado/stages/build/steps/result-analyzer.yml b/ado/stages/build/steps/result-analyzer.yml new file mode 100644 index 0000000..ff9ffb5 --- /dev/null +++ b/ado/stages/build/steps/result-analyzer.yml @@ -0,0 +1,24 @@ +steps: + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet 5.4' + inputs: + versionSpec: 5.4 + + - task: NuGetCommand@2 + displayName: 'NuGet restore' + inputs: + restoreSolution: '**\RESTlerAgent.sln' + + - task: DotNetCoreCLI@2 + displayName: 'Result Analyzer' + inputs: + command: publish + publishWebProjects: false + projects: src/Agent/RaftResultAnalyzer/RaftResultAnalyzer.fsproj + arguments: '-c release /p:version=$(versionNumber)' + zipAfterPublish: false + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: src/Agent/RaftResultAnalyzer/bin/release/netcoreapp3.1/publish/ + artifactName: RaftResultAnalyzer diff --git a/ado/stages/build/steps/test-infra.yml b/ado/stages/build/steps/test-infra.yml new file mode 100644 index 0000000..484ecfc --- /dev/null +++ b/ado/stages/build/steps/test-infra.yml @@ -0,0 +1,41 @@ +steps: + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet 5.4' + inputs: + versionSpec: 5.4 + + - task: NuGetCommand@2 + displayName: 'NuGet restore' + inputs: + restoreSolution: '**\TestInfra.sln' + + - task: DotNetCoreCLI@2 + displayName: 'TestInfra' + inputs: + command: publish + publishWebProjects: false + projects: src/Test/TestInfraFunc/TestInfraFunc.csproj + arguments: '-c release /p:version=$(versionNumber)' + zipAfterPublish: false + + - task: CopyFiles@2 + displayName: 'Copy Test Infra Dockerfile' + inputs: + targetFolder: src/Test/TestInfraFunc/bin/release/netcoreapp3.1/publish/ + sourceFolder: src/Test/ + contents: Dockerfile + + # Because we are using a a release pipeline we need to publish the Dockerfile + # in the artifacts, since the release pipeline does not have access to the code tree. + - task: CopyFiles@2 + displayName: 'Copy TestInfraFunc Dockerfile' + inputs: + targetFolder: src/Test/TestInfraFunc/bin/release/netcoreapp3.1/publish/ + sourceFolder: src/Test + contents: Dockerfile + + - task: PublishPipelineArtifact@1 + inputs: + targetPath: src/Test/TestInfraFunc/bin/release/netcoreapp3.1/publish/ + artifactName: TestInfraFunc + diff --git a/ado/stages/deploy/deploy-infrastructure.yml b/ado/stages/deploy/deploy-infrastructure.yml new file mode 100644 index 0000000..eccdc58 --- /dev/null +++ b/ado/stages/deploy/deploy-infrastructure.yml @@ -0,0 +1,8 @@ +stages: + - stage: DeployInfrastructure + jobs: + - job: DeployInfrastructure + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/deploy-infrastructure.yml diff --git a/ado/stages/deploy/deploy.yml b/ado/stages/deploy/deploy.yml new file mode 100644 index 0000000..1e2f814 --- /dev/null +++ b/ado/stages/deploy/deploy.yml @@ -0,0 +1,8 @@ + stages: + - stage: Deploy + jobs: + - job: UploadServiceUtilites_Restart + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/upload-utils.yml diff --git a/ado/stages/deploy/steps/deploy-infrastructure.yml b/ado/stages/deploy/steps/deploy-infrastructure.yml new file mode 100644 index 0000000..2bd0762 --- /dev/null +++ b/ado/stages/deploy/steps/deploy-infrastructure.yml @@ -0,0 +1,17 @@ +steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.8' + addToPath: true + + - script: pip3 install -r cli/requirements.txt + displayName: Install CLI Python requirements + + - task: AzureCLI@2 + displayName: "Deploy Service Infrastructure" + inputs: + azureSubscription: $(raft-subscription) + scriptType: 'pscore' + scriptLocation: 'inlineScript' + inlineScript: "python cli/raft.py --defaults-context-json '$(raft-defaults)' --secret $(bvt-secret) --skip-sp-deployment service deploy" + diff --git a/ado/stages/deploy/steps/restart.yml b/ado/stages/deploy/steps/restart.yml new file mode 100644 index 0000000..a7355b0 --- /dev/null +++ b/ado/stages/deploy/steps/restart.yml @@ -0,0 +1,17 @@ +steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.8' + addToPath: true + + - script: pip3 install -r cli/requirements.txt + displayName: Install CLI Python requirements + + - task: AzureCLI@2 + displayName: "Restart Services" + inputs: + azureSubscription: $(raft-subscription) + scriptType: 'pscore' + scriptLocation: 'inlineScript' + inlineScript: "python cli/raft.py --defaults-context-json '$(raft-defaults)' --secret $(bvt-secret) service restart" + diff --git a/ado/stages/deploy/steps/upload-utils.yml b/ado/stages/deploy/steps/upload-utils.yml new file mode 100644 index 0000000..96c7ed4 --- /dev/null +++ b/ado/stages/deploy/steps/upload-utils.yml @@ -0,0 +1,22 @@ +steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.8' + addToPath: true + + - script: pip3 install -r cli/requirements.txt + displayName: Install CLI Python requirements + + - task: DownloadPipelineArtifact@2 + inputs: + artifact: AzureAuth + path: cli/raft-utils/auth/dotnet-core-3.1 + + - task: AzureCLI@2 + displayName: "Upload service utilities" + inputs: + azureSubscription: $(raft-subscription) + scriptType: 'pscore' + scriptLocation: 'inlineScript' + inlineScript: "python cli/raft.py --defaults-context-json '$(raft-defaults)' --secret $(bvt-secret) service upload-utils" + diff --git a/ado/stages/publish/publish.yml b/ado/stages/publish/publish.yml new file mode 100644 index 0000000..6bed513 --- /dev/null +++ b/ado/stages/publish/publish.yml @@ -0,0 +1,40 @@ +parameters: + - name: variable_group + type: string + +stages: + - stage: Publish + jobs: + - job: APIService + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/apiservice.yml + + # It's a requirement to use a deployment job to specify the environment + # We only need one deployment, as referencing this job via the environment will show + # everything from the whole pipeline. + - deployment: Orchestrator + pool: + vmImage: 'ubuntu-latest' + environment: ${{ parameters.variable_group }} + strategy: + runOnce: + deploy: + steps: + - template: steps/orchestrator.yml + + - job: RESTleragent + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/restleragent.yml + + - job: TestInfra + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/test-infra.yml + + + diff --git a/ado/stages/publish/steps/apiservice.yml b/ado/stages/publish/steps/apiservice.yml new file mode 100644 index 0000000..0001066 --- /dev/null +++ b/ado/stages/publish/steps/apiservice.yml @@ -0,0 +1,16 @@ +steps: + - task: DownloadPipelineArtifact@2 + inputs: + artifact: apiservice + path: $(Build.SourcesDirectory)/artifacts/apiservice + + - task: Docker@2 + displayName: 'Publish APIService imageTag' + inputs: + buildContext: $(Build.SourcesDirectory)/artifacts/apiservice/ + command: buildAndPush + containerRegistry: $(raft-containerRegistryServiceConnection) + repository: restapifuzztesting/apiservice + Dockerfile: artifacts/apiservice/Dockerfile + tags: | + $(imageTag) diff --git a/ado/stages/publish/steps/orchestrator.yml b/ado/stages/publish/steps/orchestrator.yml new file mode 100644 index 0000000..6cf89aa --- /dev/null +++ b/ado/stages/publish/steps/orchestrator.yml @@ -0,0 +1,11 @@ + steps: + - task: Docker@2 + displayName: 'Publish Orchestrator imageTag' + inputs: + buildContext: $(Pipeline.Workspace)/Orchestrator/ + command: buildAndPush + containerRegistry: $(raft-containerRegistryServiceConnection) + repository: restapifuzztesting/orchestrator + Dockerfile: $(Pipeline.Workspace)/Orchestrator/Dockerfile + tags: | + $(imageTag) diff --git a/ado/stages/publish/steps/restleragent.yml b/ado/stages/publish/steps/restleragent.yml new file mode 100644 index 0000000..d0e9a6c --- /dev/null +++ b/ado/stages/publish/steps/restleragent.yml @@ -0,0 +1,30 @@ + steps: + - task: DownloadPipelineArtifact@2 + inputs: + artifact: RestlerAgent + path: $(Build.SourcesDirectory)/artifacts/RestlerAgent + + - task: DownloadPipelineArtifact@2 + inputs: + artifact: RaftResultAnalyzer + path: $(Build.SourcesDirectory)/artifacts/RaftResultAnalyzer + + # This authenticates against the service connection which is needed to pull the restler image + # from the repository. + - task: Docker@2 + displayName: Login to ACR + inputs: + command: login + containerRegistry: acrrestler + + - task: Docker@2 + displayName: 'Publish Restler Agent imageTag' + inputs: + command: buildAndPush + buildContext: $(Build.SourcesDirectory)/artifacts/ + containerRegistry: $(raft-containerRegistryServiceConnection) + repository: restapifuzztesting/restler-agent + Dockerfile: src/Agent/Dockerfile + tags: | + $(imageTag) + diff --git a/ado/stages/publish/steps/test-infra.yml b/ado/stages/publish/steps/test-infra.yml new file mode 100644 index 0000000..a430140 --- /dev/null +++ b/ado/stages/publish/steps/test-infra.yml @@ -0,0 +1,16 @@ +steps: + - task: DownloadPipelineArtifact@2 + inputs: + artifact: TestInfraFunc + path: $(Build.SourcesDirectory)/artifacts/TestInfraFunc + + - task: Docker@2 + displayName: 'Publish Test Infra imageTag' + inputs: + buildContext: $(Build.SourcesDirectory)/artifacts/TestInfraFunc/ + command: buildAndPush + containerRegistry: $(raft-containerRegistryServiceConnection) + repository: restapifuzztesting/test-infra-func + Dockerfile: $(Build.SourcesDirectory)/artifacts/TestInfraFunc/Dockerfile + tags: $(imageTag) + diff --git a/ado/stages/test/steps/bvt.yml b/ado/stages/test/steps/bvt.yml new file mode 100644 index 0000000..b51c15f --- /dev/null +++ b/ado/stages/test/steps/bvt.yml @@ -0,0 +1,16 @@ +steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.8' + addToPath: true + + - script: pip3 install -r cli/requirements.txt + displayName: Install CLI Python requirements + + - task: AzureCLI@2 + displayName: "Compile-Fuzz Test" + inputs: + azureSubscription: $(raft-subscription) + scriptType: 'pscore' + scriptLocation: 'inlineScript' + inlineScript: "python Scripts/Tests/bvt.py --defaults-context-json '$(raft-defaults)' --secret $(bvt-secret) --host $(bvt-host)" diff --git a/ado/stages/test/steps/webhooks.yml b/ado/stages/test/steps/webhooks.yml new file mode 100644 index 0000000..a0fc520 --- /dev/null +++ b/ado/stages/test/steps/webhooks.yml @@ -0,0 +1,16 @@ +steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.8' + addToPath: true + + - script: pip3 install -r cli/requirements.txt + displayName: Install CLI Python requirements + + - task: AzureCLI@2 + displayName: "List Webhook Events Test" + inputs: + azureSubscription: $(raft-subscription) + scriptType: 'pscore' + scriptLocation: 'inlineScript' + inlineScript: "python Scripts/Tests/list-available-webhook-events.py --defaults-context-json '$(raft-defaults)' --secret $(bvt-secret)" \ No newline at end of file diff --git a/ado/stages/test/test.yml b/ado/stages/test/test.yml new file mode 100644 index 0000000..8f6b0cb --- /dev/null +++ b/ado/stages/test/test.yml @@ -0,0 +1,14 @@ +parameters: + - name: RunBvt + type: string + +stages: + - stage: Test + jobs: + - job: BuildVerification + condition: and(succeeded(), eq('${{parameters.RunBvt}}', 'Yes')) + pool: + vmImage: 'ubuntu-latest' + steps: + - template: steps/webhooks.yml + - template: steps/bvt.yml diff --git a/ado/variables/version-variables.yml b/ado/variables/version-variables.yml new file mode 100644 index 0000000..0bc8051 --- /dev/null +++ b/ado/variables/version-variables.yml @@ -0,0 +1,11 @@ +variables: + - name: version.major + value: 1 + - name: version.minor + value: 0 + - name: imageTag + value: 'v1.0' + - name: devRevision + value: 0 + - name: imageTagWithBuildDate + value : $(imageTag)-$(Build.BuildNumber) diff --git a/cli/raft-utils/auth/python3/msal/msal_token.py b/cli/raft-utils/auth/python3/msal/msal_token.py new file mode 100644 index 0000000..439eb18 --- /dev/null +++ b/cli/raft-utils/auth/python3/msal/msal_token.py @@ -0,0 +1,31 @@ +import msal +import os +import json +import sys + +def get_token(client_id, tenant_id, secret, scopes, authority_uri): + + if authority_uri: + authority = f"{authority_uri}/{tenant_id}" + else: + authority = f"https://login.microsoftonline.com/{tenant_id}" + + if not scopes: + scopes = [f"{client_id}/.default"] + app = msal.ConfidentialClientApplication(client_id, authority=authority, client_credential=secret) + return app.acquire_token_for_client(scopes) + +def token_from_env_variable(env_variable_name): + auth_params = os.environ.get(f"RAFT_{env_variable_name}") or os.environ.get(env_variable_name) + if auth_params: + auth = json.loads(auth_params) + token = get_token(auth['client'], auth['tenant'], auth['secret'], auth.get('scopes'), auth.get('authorityUri') ) + print("Getting MSAL token") + return f'{token["token_type"]} {token["access_token"]}' + else: + print(f"Authentication parameters are not set in environment variable {env_variable_name}") + return None + +if __name__ == "__main__": + token = token_from_env_variable(sys.argv[1]) + print(token) \ No newline at end of file diff --git a/cli/raft-utils/auth/python3/msal/requirements.txt b/cli/raft-utils/auth/python3/msal/requirements.txt new file mode 100644 index 0000000..a04400a --- /dev/null +++ b/cli/raft-utils/auth/python3/msal/requirements.txt @@ -0,0 +1 @@ +msal~=1.4.3 diff --git a/cli/raft-utils/tools/RESTler/config.json b/cli/raft-utils/tools/RESTler/config.json new file mode 100644 index 0000000..94e4fae --- /dev/null +++ b/cli/raft-utils/tools/RESTler/config.json @@ -0,0 +1,13 @@ +{ + "container" : "{PrivateRegistryRestler}/restler-agent:v0.9.0", + "run" : { + "command" : "/bin/sh", + "arguments" : ["-c", + "dotnet /raft/agent/RestlerAgent.dll --agent-name ${RAFT_CONTAINER_NAME} --job-id ${RAFT_JOB_ID} --task-config-path ${RAFT_WORK_DIRECTORY}/task-config.json --work-directory ${RAFT_WORK_DIRECTORY} --restler-path /RESTler --app-insights-instrumentation-key ${RAFT_APP_INSIGHTS_KEY} --output-sas \"${RAFT_SB_OUT_SAS}\"" + ] + }, + "idle" : { + "command" : "/bin/sh", + "arguments" : ["-c", "echo DebugMode; while true; do sleep 100000; done;"] + } +} diff --git a/cli/raft-utils/tools/RESTler/schema.json b/cli/raft-utils/tools/RESTler/schema.json new file mode 100644 index 0000000..3512bd9 --- /dev/null +++ b/cli/raft-utils/tools/RESTler/schema.json @@ -0,0 +1,262 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "RESTler", + "version": "v1" + }, + "paths": {}, + "components": { + "schemas": { + "CustomDictionary": { + "type": "object", + "properties": { + "fuzzableString": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of string values used as fuzzing inputs. If null then values are auto-generated", + "nullable": true + }, + "fuzzableInt": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of int values used as fuzzing inputs. If null then values are auto-generated", + "nullable": true + }, + "fuzzableNumber": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of number values used as fuzzing inputs. If null then values are auto-generated", + "nullable": true + }, + "fuzzableBool": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of bool values used as fuzzing inputs. If null then values are auto-generated", + "nullable": true + }, + "fuzzableDatetime": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of date-time values used as fuzzing inputs. If null then values are auto-generated", + "nullable": true + }, + "fuzzableObject": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of string encoded JSON objects values used as fuzzing inputs", + "nullable": true + }, + "fuzzableUuid4": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of UUID4 values used as fuzzing inputs", + "nullable": true + }, + "customPayload": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Map of values to use as replacement of parameters defined in Swagger specifications. For example\r\nif { \"userId\" : [\"a\", \"b\"] } is specified then {userId} in URL path /users/{userId} will be replaced\r\nby \"a\" or by \"b\"", + "nullable": true + }, + "customPayloadUuid4Suffix": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Map of values to use as replacement of parameters defined in swagger. The values will\r\nhave a random suffix added. For example {\"publicIpAddressName\": \"publicIpAddrName-\"} will produce publicIpAddrName-f286a0a069 for\r\npublicIpAddressName parameter defined in Swagger specifications.", + "nullable": true + }, + "customPayloadHeader": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "User specified custom headers to pass in every request", + "nullable": true + }, + "shadowValues": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "RESTler documentation will have more info on this", + "nullable": true + } + }, + "additionalProperties": false + }, + "CompileConfiguration": { + "type": "object", + "properties": { + "inputJsonGrammarPath": { + "type": "string", + "description": "Path to a JSON grammar to use for compilation\r\nIf set then JSON grammar used for compilation instead of Swagger", + "nullable": true + }, + "inputFolderPath": { + "type": "string", + "description": "Grammar is produced by compile step prior. The compile step\r\nfile share is mounted and set here. Agent will not modify\r\nthis share. Agent will make a copy of all needed files to it's work directory\r\nand re-run compile with data passed through this folder.", + "nullable": true + }, + "readOnlyFuzz": { + "type": "boolean", + "description": "When true, only fuzz the GET requests" + }, + "allowGetProducers": { + "type": "boolean", + "description": "Allows GET requests to be considered.\r\nThis option is present for debugging, and should be\r\nset to 'false' by default.\r\nIn limited cases when GET is a valid producer, the user\r\nshould add an annotation for it." + }, + "useRefreshableToken": { + "type": "boolean", + "description": "Use refreshable token for authenticating with service under test" + }, + "mutationsSeed": { + "type": "integer", + "description": "Use the seed to generate random value for empty/null customDictitonary fields\r\nif not set then default hard-coded RESTler values are used for populating customDictionary fields", + "format": "int64", + "nullable": true + }, + "customDictionary": { + "$ref": "#/components/schemas/CustomDictionary" + } + }, + "additionalProperties": false, + "description": "User-specified RESTler compiler configuration" + }, + "TargetEndpointConfiguration": { + "type": "object", + "properties": { + "ip": { + "type": "string", + "description": "The IP of the endpoint being fuzzed", + "nullable": true + }, + "port": { + "type": "integer", + "description": "The port of the endpoint being fuzzed. Defaults to 443.", + "format": "int32" + } + }, + "additionalProperties": false, + "description": "Configuration of the endpoint under test" + }, + "RunConfiguration": { + "type": "object", + "properties": { + "grammarPy": { + "type": "string", + "description": "Path to grammar py relative to compile folder path. If not set then default \"grammar.py\" grammar is assumed", + "nullable": true + }, + "inputFolderPath": { + "type": "string", + "description": "For Test or Fuzz tasks: Grammar is produced by compile step. The compile step\r\nfile share is mounted and set here. Agent will not modify\r\nthis share. Agent will make a copy of all needed files to it's work directory.\r\nFor Replay task: path to RESTler Fuzz or Test run that contains bug buckets to replay", + "nullable": true + }, + "targetEndpointConfiguration": { + "$ref": "#/components/schemas/TargetEndpointConfiguration" + }, + "producerTimingDelay": { + "type": "integer", + "description": "The delay in seconds after invoking an API that creates a new resource", + "format": "int32" + }, + "useSsl": { + "type": "boolean", + "description": "Use SSL when connecting to the server" + }, + "pathRegex": { + "type": "string", + "description": "Path regex for filtering tested endpoints", + "nullable": true + } + }, + "additionalProperties": false, + "description": "RESTler job Test, Fuzz or Replay configuration" + }, + "ReplayConfiguration": { + "type": "object", + "properties": { + "replayBugBucketsPaths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of paths to RESTler folder runs to replay (names of folders are assigned when mounted readonly/readwrite file share mounts).\r\nIf path is a folder, then all bug buckets replayed in the folder.\r\nIf path is a bug_bucket file - then only that file is replayed.\r\nIf empty - then replay all bugs under RunConfiguration.previousStepOutputFolderPath.", + "nullable": true + }, + "runConfiguration": { + "$ref": "#/components/schemas/RunConfiguration" + } + }, + "additionalProperties": false, + "description": "RESTler configuration for replaying request sequences that triggered a reproducable bug" + }, + "AgentConfiguration": { + "type": "object", + "properties": { + "resultsAnalyzerReportTimeSpanInterval": { + "type": "string", + "description": "How often to run result analyzer against RESTler logs. Default is every 1 minute.\r\nIf not set then result analyzer will run only once after RESTler task is over.", + "format": "date-span", + "nullable": true + } + }, + "additionalProperties": false, + "description": "Configure behaviour of RESTler agent" + }, + "RESTler": { + "type": "object", + "properties": { + "task": { + "type": "string", + "description": "Can be compile, fuzz, test, replay", + "nullable": false + }, + "compileConfiguration": { + "$ref": "#/components/schemas/CompileConfiguration" + }, + "runConfiguration": { + "$ref": "#/components/schemas/RunConfiguration" + }, + "replayConfiguration": { + "$ref": "#/components/schemas/ReplayConfiguration" + }, + "agentConfiguration": { + "$ref": "#/components/schemas/AgentConfiguration" + }, + }, + "additionalProperties": false, + "description": "RESTler payload" + } + } + } +} diff --git a/cli/raft-utils/tools/ZAP/config.json b/cli/raft-utils/tools/ZAP/config.json new file mode 100644 index 0000000..cfd1e73 --- /dev/null +++ b/cli/raft-utils/tools/ZAP/config.json @@ -0,0 +1,13 @@ +{ + "container" : "owasp/zap2docker-stable", + "run" : { + "command" : "bash", + "arguments" : ["-c", + "touch /.dockerenv; cd $RAFT_RUN_DIRECTORY; ln -s $RAFT_WORK_DIRECTORY /zap/wrk; python3 run.py install; python3 run.py" ] + }, + "idle" : { + "command" : "bash", + "arguments" : ["-c", "echo DebugMode; while true; do sleep 100000; done;"] + } +} + diff --git a/cli/raft-utils/tools/ZAP/requirements.txt b/cli/raft-utils/tools/ZAP/requirements.txt new file mode 100644 index 0000000..372a51c --- /dev/null +++ b/cli/raft-utils/tools/ZAP/requirements.txt @@ -0,0 +1,2 @@ +applicationinsights +azure-servicebus \ No newline at end of file diff --git a/cli/raft-utils/tools/ZAP/run.py b/cli/raft-utils/tools/ZAP/run.py new file mode 100644 index 0000000..764a01c --- /dev/null +++ b/cli/raft-utils/tools/ZAP/run.py @@ -0,0 +1,48 @@ +import json +import os +import subprocess +import sys + +work_directory = os.environ['RAFT_WORK_DIRECTORY'] +run_directory = os.environ['RAFT_RUN_DIRECTORY'] + +def auth_token(init): + with open(os.path.join(work_directory, "task-config.json"), 'r') as task_config: + config = json.load(task_config) + auth_config = config.get("authenticationMethod") + if auth_config: + if auth_config.get("TxtToken"): + token = os.environ.get(f"RAFT_{auth_config['TxtToken']}") or os.environ.get(auth_config["TxtToken"]) + return token + elif auth_config.get("CommandLine"): + subprocess.getoutput(auth_config.get("CommandLine")) + elif auth_config.get("MSAL"): + msal_dir = os.path.join(run_directory, "..", "..", "auth", "python3", "msal") + + if init: + print("Installing MSAL requirements") + subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", os.path.join(msal_dir, "requirements.txt")]) + else: + print("Retrieving MSAL token") + sys.path.append(msal_dir) + authentication_environment_variable = auth_config["MSAL"] + import msal_token + token = msal_token.token_from_env_variable( authentication_environment_variable ) + if token: + print("Retrieved MSAL token") + return token + else: + print("Failed to retrieve MSAL token") + return None + else: + print(f'Unhandled authentication configuration {auth_config}') + return None + +if __name__ == "__main__": + if len(sys.argv) == 2 and sys.argv[1] == "install": + subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", os.path.join(run_directory, "requirements.txt")]) + auth_token(True) + else: + token = auth_token(False) + import scan + scan.run(token) diff --git a/cli/raft-utils/tools/ZAP/scan.py b/cli/raft-utils/tools/ZAP/scan.py new file mode 100644 index 0000000..8959e4b --- /dev/null +++ b/cli/raft-utils/tools/ZAP/scan.py @@ -0,0 +1,159 @@ +import os +import sys +import json +import shutil +import time +import io +import logging +from logging import StreamHandler + +from applicationinsights import TelemetryClient +from azure.servicebus import TopicClient, Message +from contextlib import redirect_stdout + +class RaftUtils(): + def __init__(self): + work_directory = os.environ['RAFT_WORK_DIRECTORY'] + with open(os.path.join(work_directory, 'task-config.json'), 'r') as task_config: + self.config = json.load(task_config) + + connection_str = os.environ['RAFT_SB_OUT_SAS'] + self.topic_client = TopicClient.from_connection_string(connection_str) + + self.telemetry_client = TelemetryClient(instrumentation_key=os.environ['RAFT_APP_INSIGHTS_KEY']) + + self.job_id = os.environ['RAFT_JOB_ID'] + self.container_name = os.environ['RAFT_CONTAINER_NAME'] + + self.telemetry_properties = { + "jobId" : self.job_id, + "taskIndex" : os.environ['RAFT_TASK_INDEX'], + "containerName" : self.container_name + } + + def report_status(self, state, details): + m = { + 'eventType' : 'JobStatus', + 'message': { + 'tool' : 'ZAP', + 'jobId' : self.job_id, + 'agentName': self.container_name, + 'details': details, + 'utcEventTime' : time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()), + 'state' : state + } + } + msg = Message(str.encode(json.dumps(m))) + self.topic_client.send(msg) + + def report_status_created(self, details=None): + self.report_status('Created', details) + + def report_status_running(self, details=None): + self.report_status('Running', details) + + def report_status_error(self, details=None): + self.report_status('Error', details) + + def report_status_completed(self, details=None): + self.report_status('Completed', details) + + def log_trace(self, trace): + self.telemetry_client.track_trace(trace, properties=self.telemetry_properties) + + def log_exception(self): + self.telemetry_client.track_exception(properties=self.telemetry_properties) + + def flush(self): + self.telemetry_client.flush() + + def get_swagger_target(self): + swagger = self.config.get("swaggerLocation") + if swagger and swagger.get("url"): + return swagger["url"] + elif swagger.get("filePath"): + return swagger["filePath"] + + +zap_dir = '/zap' +sys.path.append(zap_dir) +zap = __import__("zap-api-scan") + +utils = RaftUtils() + +class StatusReporter(StreamHandler): + def __init__(self): + StreamHandler.__init__(self) + self.last_txt = None + + def emit(self, record): + txt = self.format(record) + if txt != self.last_txt: + self.last_txt = txt + progress='Active Scan progress %:' + i = txt.find(progress) + if i != -1: + utils.report_status_running([txt[i :]]) + +def run_zap(token): + target = utils.get_swagger_target() + if token: + utils.log_trace('Authentication token is set') + auth = ('-config replacer.full_list(0).description=auth1' + ' -config replacer.full_list(0).enabled=true' + ' -config replacer.full_list(0).matchtype=REQ_HEADER' + ' -config replacer.full_list(0).matchstr=Authorization' + ' -config replacer.full_list(0).regex=false' + f' -config replacer.full_list(0).replacement="{token}"') + zap_auth_config = ['-z', auth] + else: + utils.log_trace('Authentication token is not set') + zap_auth_config = [] + + os.chdir(zap_dir) + r = 0 + try: + print('Removing zap.out if exists') + os.remove('/zap/zap.out') + except: + pass + + try: + utils.log_trace("Starting ZAP") + utils.report_status_running() + + status_reporter = StatusReporter() + logger = logging.getLogger() + logger.addHandler(status_reporter) + zap.main(['-t', target, '-f', 'openapi', '-J', 'report.json', '-r', 'report.html', '-w', 'report.md', '-x', 'report.xml', '-d'] + zap_auth_config) + + except SystemExit as e: + r = e.code + + utils.log_trace(f"ZAP exited with exit code: {r}") + shutil.copy('/zap/zap.out', '/zap/wrk/zap.out') + + utils.report_status_completed() + if r < 2: + return 0 + else: + return r + +def run(token): + try: + utils.report_status_created() + return run_zap(token) + except Exception as ex: + utils.log_exception() + utils.report_status_error([f"{ex}"]) + raise + finally: + utils.flush() + + +if __name__ == "__main__": + if len(sys.argv) == 2: + run(sys.argv[1]) + else: + run(None) + diff --git a/cli/raft.py b/cli/raft.py new file mode 100644 index 0000000..337f204 --- /dev/null +++ b/cli/raft.py @@ -0,0 +1,460 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +import argparse +import json +import os +import uuid +import textwrap + +import raft_sdk.raft_common +from raft_sdk.raft_service import RaftCLI, RaftJobConfig +from raft_sdk.raft_deploy import RaftServiceCLI + +script_dir = os.path.dirname(os.path.abspath(__file__)) + +fresh_defaults = json.dumps( + { + "subscription": "", + "deploymentName": "", + "region": "", + "metricsOptIn": True, + "useAppInsights": True, + "registry": "mcr.microsoft.com" + }, indent=4) + +defaults_help = ''' +subscription - The Azure Subscription ID to which RAFT is deployed + +deploymentName - RAFT deployment name + deployment name requirements: + - only letters or numbers + - at most 20 characters long + - no capital letters + - no dashes + +region - Region to deploy RAFT (e.g. westus2) + https://docs.microsoft.com/en-us/azure/container-instances/container-instances-region-availability + for to pick the optimal region for your deployment. + All jobs will be deployed by default in the same + region as your service deployment + +metricsOptIn - allow Microsoft collect anonymized metrics from the deployment. + +useAppInsights - deploy AppInsights and use it to write all service logs + +registry - registry which stores service images. + Default: mcr.microsoft.com + +------------------------- +To apply any changes made to the defaults.json file, +please run 'raft.py service deploy' +------------------------- +''' + + +def run(args): + def validate(defaults): + s = defaults.get('subscription') + d = defaults.get('deploymentName') + r = defaults.get('region') + return (s and d and r) + + defaults_path = args['defaults_context_path'] + defaults_json = args['defaults_context_json'] + + if defaults_json: + print(f"Loading defaults from command line: {defaults_json}") + defaults = json.loads(defaults_json) + if not validate(defaults): + print(defaults_help) + return + # check if defaults.json is set in the context and it exists + elif os.path.isfile(defaults_path): + with open(defaults_path, 'r') as d: + defaults = json.load(d) + if not validate(defaults): + print(defaults_help) + return + else: + with open(defaults_path, 'w') as d: + d.write(fresh_defaults) + print(defaults_help) + return + + defaults['secret'] = args.get('secret') + if 'metricsOptIn' not in defaults: + defaults['metricsOptIn'] = True + + if defaults.get('useAppInsights') is None: + defaults['useAppInsights'] = True + + cli_action = args.get('logout') + service_action = args.get('service-action') + job_action = args.get('job-action') + webhook_action = args.get('webhook-action') + + if cli_action == 'logout': + raft_sdk.raft_common.delete_token_cache() + elif service_action: + service_cli = RaftServiceCLI(defaults, defaults_path) + + if service_action == 'restart': + service_cli.restart() + elif service_action == 'info': + info = service_cli.service_info() + print(info) + elif service_action == 'deploy': + skip_sp_deployment = args.get('skip_sp_deployment') + service_cli.deploy( + args['sku'], skip_sp_deployment and skip_sp_deployment is True) + elif service_action == 'upload-utils': + utils_file_share = f'{uuid.uuid4()}' + service_cli.upload_utils(utils_file_share) + service_cli.restart() + else: + raise Exception(f'Unhandled service argument: {service_action}') + + elif job_action: + cli = RaftCLI() + if job_action == 'create': + json_config_path = args.get('file') + if json_config_path is None: + ArgumentRequired('--file') + + substitutionDictionary = {} + substitutionParameter = args.get('substitute') + if substitutionParameter: + substitutionDictionary = json.loads(substitutionParameter) + + job_config = RaftJobConfig(file_path=json_config_path, + substitutions=substitutionDictionary) + + print(job_config.config) + duration = args.get('duration') + if duration: + job_config.config['duration'] = duration + + metadata = args.get('metadata') + if metadata: + job_config.config['metadata'] = json.loads(metadata) + + newJob = cli.new_job(job_config, args.get('region')) + poll_interval = args.get('poll') + if poll_interval: + print(newJob) + cli.poll(newJob['jobId'], poll_interval) + else: + print(newJob) + + elif job_action == 'status': + job_id = args.get('job_id') + if job_id is None: + ArgumentRequired('--job-id') + job_status = cli.job_status(job_id) + poll_interval = args.get('poll') + cli.print_status(job_status) + if poll_interval: + cli.poll(job_id, poll_interval) + + elif job_action == 'list': + jobs_list = cli.list_jobs(args['look_back_hours']) + sorted = {} + for job in jobs_list: + if sorted.get(job['jobId']): + sorted[job['jobId']].append(job) + else: + sorted[job['jobId']] = [job] + + for s in sorted: + cli.print_status(sorted[s]) + print() + + print(f"Total number of jobs: {len(sorted)}") + + elif job_action == 'update': + json_config_path = args.get('file') + if json_config_path is None: + ArgumentRequired('--file') + + substitutionDictionary = {} + substitutionParameter = args.get('substitute') + if substitutionParameter: + substitutionDictionary = json.loads(substitutionParameter) + + job_update = cli.update_job( + args.get('job-id'), + RaftJobConfig(file_path=json_config_path, + substitutions=substitutionDictionary)) + print(job_update) + + elif job_action == 'results': + job_id = args.get('job_id') + if job_id is None: + ArgumentRequired('--job-id') + url = cli.result_url(job_id) + print(url) + + elif job_action == 'delete': + job_id = args.get('job_id') + if job_id is None: + ArgumentRequired('--job-id') + job_delete = cli.delete_job(job_id) + print(job_delete) + + elif webhook_action: + cli = RaftCLI() + if webhook_action == 'events': + webhook_events = cli.list_available_webhooks_events() + print(webhook_events) + + elif webhook_action == 'create': + name_parameter = args.get('name') + if name_parameter is None: + ArgumentRequired('--name') + + event_parameter = args.get('event') + if event_parameter is None: + ArgumentRequired('--event') + + uri_parameter = args.get('url') + if uri_parameter is None: + ArgumentRequired('--url') + + webhook_create_or_update = cli.set_webhooks_subscription( + name_parameter, event_parameter, uri_parameter) + print(webhook_create_or_update) + + elif webhook_action == 'test': + name_parameter = args.get('name') + if name_parameter is None: + ArgumentRequired('--name') + + event_parameter = args.get('event') + if event_parameter is None: + ArgumentRequired('--event') + + webhook_test = cli.test_webhook(name_parameter, event_parameter) + print(webhook_test) + + elif webhook_action == 'delete': + name_parameter = args.get('name') + if name_parameter is None: + ArgumentRequired('--name') + + event_parameter = args.get('event') + if event_parameter is None: + ArgumentRequired('--event') + + webhook_delete = cli.delete_webhook(name_parameter, + event_parameter) + print(webhook_delete) + + elif webhook_action == 'list': + name_parameter = args.get('name') + if name_parameter is None: + ArgumentRequired('--name') + + # the event name is not required. + # If not supplied all events will be listed. + event_parameter = args.get('event') + + webhooks_list = cli.list_webhooks(name_parameter, event_parameter) + print(webhooks_list) + + else: + raise Exception('Expected arguments could not be found in args') + + +def ArgumentRequired(name): + print(f'The {name} parameter is required') + quit() + + +def add_defaults_and_secret_args(parser): + parser.add_argument( + "--defaults-context-path", + default=os.path.join(script_dir, 'defaults.json'), + help="Path to the defaults.json", + required=False + ) + parser.add_argument( + "--defaults-context-json", + default=None, + help="JSON blob containing service configuration", + required=False + ) + parser.add_argument('--secret', required=False) + parser.add_argument('--skip-sp-deployment', + required=False, + action='store_true') + + +# pip install -r requirements.txt +def main(): + parser = argparse.ArgumentParser( + description='RAFT CLI', + formatter_class=argparse.RawTextHelpFormatter) + sub_parser = parser.add_subparsers() + + cli_parser = sub_parser.add_parser( + 'cli', + formatter_class=argparse.RawTextHelpFormatter) + + cli_parser.add_argument('logout', + help=textwrap.dedent('''\ +Clears the cache so re-authentication will be needed to use the CLI again.''')) + + service_parser = sub_parser.add_parser( + 'service', + formatter_class=argparse.RawTextHelpFormatter) + service_parser.add_argument( + 'service-action', + choices=['deploy', 'restart', 'info', 'upload-utils'], + help=textwrap.dedent('''\ +deploy - Deploys the service + +restart - Restarts the service updating the + docker containers if a new one is available + +info - Show the version of the service and the last time it was started + +upload-utils - Uploads the tool definitions to the service +''')) + + allowed_skus = [ + 'B1', 'B2', 'B3', 'D1', 'F1', 'FREE', + 'I1', 'I2', 'I3', 'P1V2', 'P2V2', 'P3V2', + 'PC2', 'PC3', 'PC4', 'S1', 'S2', 'S3', 'SHARED'] + + service_parser.add_argument( + '--sku', default='B2', + choices=allowed_skus, required=False, help='Default value: B2') + + # Add the positional argument. + job_parser = sub_parser.add_parser( + 'job', + formatter_class=argparse.RawTextHelpFormatter) + + job_parser.add_argument( + 'job-action', + choices=['create', 'update', 'delete', 'status', 'list', 'results'], + help=textwrap.dedent('''\ +create - Create a new job + --file is required + +update - Update an existing job + --file is required + +delete - Delete a job + --job-id is required + +status - Get the status of a job + --job-id is required + +list - Get a list of jobs + Use --look-back-hours to specify how far back to look + the default is 24 hours + +results - Get the Uri of the job results + ''')) + + # Add the flag arguments + # This is a list of all the possible flags that can be + # used with any of the job choices. + # When parsing the job choice, the "required" flags will be enforced. + job_parser.add_argument( + '--file', + help=textwrap.dedent('''\ +File path to the job definition file. +Required for 'create' and 'update' commands''')) + + job_parser.add_argument( + '--poll', type=int, + help='Interval in seconds used to poll for job status') + + job_parser.add_argument( + '--look-back-hours', + default=24, + help='The number of hours look back for job status') + + job_parser.add_argument( + '--duration', + help='The duration in hours that a job should run') + + job_parser.add_argument( + '--region', + help='''\ +Optional parameter to run a job in a specific region. +If no region is specified the job runs in the same +region where the service is deployed +https://docs.microsoft.com/en-us/azure/container-instances/container-instances-region-availability +''') + + job_parser.add_argument( + '--metadata', + help='Arbitrary key/value pairs that will be included in webhooks.') + + job_parser.add_argument( + '--job-id', + help="Id of the job to update, required for 'status' and 'delete'") + + job_parser.add_argument( + '--substitute', + help=textwrap.dedent('''\ +Dictionary of values to find and replace in the --file. +Should be in the form {"find1":"replace1", "find2":"replace2"} +This parameter is only valid with the create and update commands + ''')) + + # The webhook positional arguments + webhook_parser = sub_parser.add_parser( + 'webhook', + formatter_class=argparse.RawTextHelpFormatter) + + webhook_parser.add_argument( + 'webhook-action', + choices=['create', 'delete', 'list', 'events', 'test'], + help=textwrap.dedent('''\ +create - Create a new webhook + --name, --event, and --url are required parameters + +delete - Delete a webhook + --name is required + +list - List a webhook + --name is required + +events - List the supported events + +test - Test a webhook + --name and --event are required +''')) + + # Add the flag arguments + # This is a list of all the possible flags that + # can be used with any of the webhook choices. + # When parsing the webhook choice, the "required" + # flags will be enforced. + webhook_parser.add_argument( + '--event', + help=textwrap.dedent('''\ +Identifies the webhook hook event, for example JobStatus or BugFound''')) + + webhook_parser.add_argument( + '--url', + help='The webhook Url which will accept the POST command') + webhook_parser.add_argument( + '--name', + help='Name of the webhook') + + add_defaults_and_secret_args(parser) + args = parser.parse_args() + + run(vars(args)) + + +if __name__ == "__main__": + try: + main() + except Exception as ex: + print(ex) diff --git a/cli/raft_sdk/raft_common.py b/cli/raft_sdk/raft_common.py new file mode 100644 index 0000000..f6bd754 --- /dev/null +++ b/cli/raft_sdk/raft_common.py @@ -0,0 +1,154 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +import msal +import requests +import os +import atexit +import string +from pathlib import Path + +script_dir = os.path.dirname(os.path.abspath(__file__)) +cache_dir = os.path.join(str(Path.home()), '.cache', 'raft') +cache_path = os.path.join(cache_dir, 'token_cache.bin') + + +def delete_token_cache(): + try: + os.remove(cache_path) + except OSError: + pass + + +# https://msal-python.readthedocs.io/en/latest/#tokencache +def token_cache(): + if not os.path.isdir(cache_dir): + os.makedirs(cache_dir) + + cache = msal.SerializableTokenCache() + + if os.path.exists(cache_path): + cache.deserialize(open(cache_path, "r").read()) + + atexit.register( + lambda: open(cache_path, "w").write(cache.serialize()) + if cache.has_state_changed else None) + return cache + + +cache = token_cache() + + +def get_auth_token(client_id, tenant_id, secret=None): + authority = f"https://login.microsoftonline.com/{tenant_id}" + scopes = [f"{client_id}/.default"] + + if secret: + app = msal.ConfidentialClientApplication( + client_id, + authority=authority, + client_credential=secret, + token_cache=cache + ) + + return app.acquire_token_for_client(scopes) + else: + app = msal.PublicClientApplication( + client_id, + authority=authority, + token_cache=cache + ) + + accounts = app.get_accounts(None) + if accounts and app.acquire_token_silent(scopes, accounts[0]): + return app.acquire_token_silent(scopes, accounts[0]) + else: + flow = app.initiate_device_flow(scopes) + print(flow['message'], flush=True) + return app.acquire_token_by_device_flow(flow) + + +class RaftApiException(Exception): + def __init__(self, message, status_code): + self.message = message + self.status_code = status_code + + +class RestApiClient(): + def __init__(self, endpoint, client_id, tenant_id, secret): + self.endpoint = endpoint + self.client_id = client_id + self.tenant_id = tenant_id + self.secret = secret + + def auth_header(self): + token = get_auth_token(self.client_id, self.tenant_id, self.secret) + if 'error_description' in token: + raise RaftApiException(token['error_description'], 400) + return { + 'Authorization': f"{token['token_type']} {token['access_token']}" + } + + def post(self, relative_url, json_data): + return requests.post( + self.endpoint + relative_url, + json=json_data, + headers=self.auth_header()) + + def put(self, relative_url, json_data): + return requests.put( + self.endpoint + relative_url, + json=json_data, + headers=self.auth_header()) + + def delete(self, relative_url): + return requests.delete( + self.endpoint + relative_url, + headers=self.auth_header()) + + def get(self, relative_url): + return requests.get( + self.endpoint + relative_url, + headers=self.auth_header()) + + +class RaftDefinitions(): + def __init__(self, context): + self.context = context + self.deployment = context['deploymentName'] + + if len(self.deployment) > 24: + raise Exception("Deployment name must be no" + " more than 24 characters long") + + for c in self.deployment: + if (c not in string.ascii_lowercase) and (c not in string.digits): + raise Exception("Deployment name" + " must use lowercase" + " letters and numbers" + " only") + self.subscription = context['subscription'] + + self.resource_group = f"{self.deployment}-raft" + self.service_bus = f"{self.deployment}-raft-servicebus" + self.app_insights = f"{self.deployment}-raft-ai" + self.asp = f"{self.deployment}-raft-asp" + self.container_tag = "v1.0" + self.queues = { + 'job_events': "raft-jobevents", + 'create_queue': "raft-jobcreate", + 'delete_queue': "raft-jobdelete" + } + + self.orchestrator = f"{self.deployment}-raft-orchestrator" + self.storage_suffix = self.subscription.split('-')[1] + self.storage_account = f"{self.deployment}raft" + self.storage_suffix + self.event_domain = f"{self.deployment}-raft-events" + self.storage_utils = f"{self.deployment}raftutil" + self.storage_suffix + self.storage_results = f"{self.deployment}raftrslt" + self.storage_suffix + self.api_service_webapp = f"{self.deployment}-raft-apiservice" + self.endpoint = f"https://{self.api_service_webapp}.azurewebsites.net" + + self.test_infra = f"{self.deployment}-raft-test-infra" + self.test_infra_storage = (f"{self.deployment}rafttest" + f"{self.storage_suffix}") + self.key_vault = f"{self.deployment}-raft-kv" diff --git a/cli/raft_sdk/raft_deploy.py b/cli/raft_sdk/raft_deploy.py new file mode 100644 index 0000000..2a1547f --- /dev/null +++ b/cli/raft_sdk/raft_deploy.py @@ -0,0 +1,1205 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import json +import hashlib +import os +import pathlib +import sys +import string +import subprocess +import time +import uuid + +from subprocess import PIPE + +import requests +from .raft_common import RaftApiException, RestApiClient, RaftDefinitions + +script_dir = os.path.dirname(os.path.abspath(__file__)) +tmp_dir = os.path.join(script_dir, '.tmp') +if not os.path.isdir(tmp_dir): + os.mkdir(tmp_dir) + +dos2unix_file_types = [".sh", ".bash"] + + +class RaftAzCliException(Exception): + def __init__(self, error_message, args): + self.error_message = error_message + self.az_args = args + + def __str__(self): + return (f"args: {self.az_args}" + f"{os.linesep}" + f"std error: {self.error_message}") + + +def az(args): + r = subprocess.run("az " + args, shell=True, stdout=PIPE, stderr=PIPE) + stdout = r.stdout.decode() + stderr = r.stderr.decode() + + if stderr and not stdout: + raise RaftAzCliException(stderr, r.args) + else: + return stdout + + +def az_json(args): + return json.loads(az(args)) + + +def azure_function_keys( + subscription_id, resource_group, function_app, function): + uri = (f"/subscriptions/{subscription_id}" + f"/resourceGroups/{resource_group}" + f"/providers/Microsoft.Web/sites/{function_app}" + f"/functions/{function}/listkeys?api-version=2018-11-01") + return az_json(f'rest --method post --uri {uri} --output json') + + +class RaftServiceCLI(): + def __init__(self, context, defaults_path): + self.defaults_path = defaults_path + self.context = context + self.definitions = RaftDefinitions(self.context) + + if self.context['metricsOptIn'] is True: + self.metrics_app_insights_key = ( + '9d67f59d-4f44-475c-9363-d0ae7ea61e95') + else: + self.metrics_app_insights_key = '' + self.site_hash = self.hash( + self.definitions.subscription + self.definitions.deployment) + + az(f'account set --subscription {self.definitions.subscription}') + + def hash(self, txt): + h = hashlib.md5() + h.update(txt.encode('utf-8')) + return h.hexdigest() + + def init_service_bus(self): + sb = self.definitions.service_bus + rg = self.definitions.resource_group + print(f'Creating service bus {sb}') + az('servicebus namespace create' + f' --resource-group {rg}' + f' --name {sb}' + f' --location {self.context["region"]}' + ' --sku Standard') + + print("Creating READ authorization rule") + az('servicebus namespace authorization-rule create' + f' --resource-group {rg}' + f' --namespace-name {sb}' + ' --name "Read" --rights Listen') + read_sb_sas = az_json( + 'servicebus namespace' + ' authorization-rule keys list' + f' --resource-group {rg}' + f' --namespace-name {sb}' + ' --name "Read"') + + print("Creating SEND authorization rule") + az('servicebus namespace authorization-rule create' + f' --resource-group {rg}' + f' --namespace-name {sb}' + ' --name "Send" --rights Send') + + send_sb_sas = az_json( + 'servicebus namespace' + ' authorization-rule keys list' + f' --resource-group {rg}' + f' --namespace-name {sb}' + ' --name "Send"') + + print("Creating queue queues.CreateQueue") + az('servicebus queue create' + f' --resource-group {rg}' + f' --namespace-name {sb}' + f' --name {self.definitions.queues["create_queue"]}' + ' --enable-session true') + + print("Creating queue queues.RESTler.DeleteQueue") + az('servicebus queue create' + f' --resource-group {rg}' + f' --namespace-name {sb}' + f' --name {self.definitions.queues["delete_queue"]}' + ' --enable-session true') + + print("Creating topic queues.RESTler.JobEvents") + az('servicebus topic create' + f' --resource-group {rg}' + f' --namespace-name {sb}' + f' --name {self.definitions.queues["job_events"]}' + ' --enable-ordering true') + + print("Creating SEND JobEvents authorization rule") + az('servicebus topic authorization-rule create' + f' --resource-group {rg}' + f' --namespace-name {sb}' + f' --topic-name {self.definitions.queues["job_events"]}' + ' --name "Send-Events" --rights Send') + + send_events_sb_sas = az_json( + 'servicebus topic' + ' authorization-rule keys list' + f' --resource-group {rg}' + f' --namespace-name {sb}' + f' --topic-name {self.definitions.queues["job_events"]}' + ' --name "Send-Events"') + + print("Creating job status events handler topic subscription") + az('servicebus topic subscription create' + f' --resource-group {rg}' + f' --namespace-name {sb}' + ' --topic-name' + f' {self.definitions.queues["job_events"]}' + ' --name "jobstatus-handler"') + + ''' Does not work due to bug in az CLI: + https://github.com/Azure/azure-cli/issues/12369 + Log "Creating filter rule for job status events" + az servicebus topic subscription rule create + --resource-group $global:raft:resourceGroup + --namespace-name $global:raft:serviceBus + --topic-name $global:raft:queues.JobEvents + --subscription-name "jobstatus-handler" + --name "JobStatus" + + Log "Set filter properties for job status events" + az servicebus topic subscription rule update + --resource-group $global:raft:resourceGroup + --namespace-name $global:raft:serviceBus + --topic-name $global:raft:queues.JobEvents + --subscription-name "jobstatus-handler" + --name "JobStatus" + --set "correlationFilter.properties.jobstatus=true" + ''' + + print("Creating web hooks handler topic subscription") + az('servicebus topic subscription create' + f' --resource-group {rg}' + f' --namespace-name {sb}' + ' --topic-name' + f' {self.definitions.queues["job_events"]}' + ' --name "webhooks-handler"') + + ''' + Does not work due to bug in az CLI: + https://github.com/Azure/azure-cli/issues/12369 + Log "Set filter properties for job status events" + az servicebus topic subscription rule create + --resource-group $global:raft:resourceGroup + --namespace-name $global:raft:serviceBus + --topic-name $global:raft:queues.JobEvents + --subscription-name "webhooks-handler" + --name "Webhooks" + + az servicebus topic subscription rule update + --resource-group $global:raft:resourceGroup + --namespace-name $global:raft:serviceBus + --topic-name $global:raft:queues.JobEvents + --subscription-name "jobstatus-handler" + --name "Webhooks" ` + --set "correlationFilter.properties.webhooks=true" + ''' + return { + 'read_sb_sas': read_sb_sas['primaryConnectionString'], + 'send_sb_sas': send_sb_sas['primaryConnectionString'], + 'send_events_sb_sas': send_events_sb_sas['primaryConnectionString'] + } + + def init_key_vault(self): + print(f'Initializing Key Vault {self.definitions.key_vault}') + az_json('keyvault create' + f' --location {self.context["region"]}' + f' --enable-rbac-authorization true' + f' --name {self.definitions.key_vault}' + ' --resource-group' + f' {self.definitions.resource_group}') + + def assign_keyvault_roles(self, sp_app_id): + print('Assigning Key Vault roles') + + scope = (f'/subscriptions/{self.definitions.subscription}' + f'/resourceGroups/{self.definitions.resource_group}' + '/providers/Microsoft.KeyVault' + f'/vaults/{self.definitions.key_vault}') + + account = az_json('ad signed-in-user show') + if 'userPrincipalName' in account: + az('role assignment create' + f' --assignee {account["userPrincipalName"]}' + ' --role "Key Vault Secrets Officer (preview)"' + f' --scope "{scope}"') + + az('role assignment create' + f' --assignee {sp_app_id}' + ' --role "Key Vault Secrets User (preview)"' + f' --scope "{scope}"') + + def assign_resource_group_roles(self, sp_app_id): + print('Assigning Resource Group roles') + scope = (f'/subscriptions/{self.definitions.subscription}' + f'/resourceGroups/{self.definitions.resource_group}') + az('role assignment create' + f' --assignee {sp_app_id}' + ' --role contributor' + f' --scope "{scope}"') + + def init_app_insights(self): + if self.context['useAppInsights']: + print(f'Initializing AppInsights {self.definitions.app_insights}') + + app_insights_installed = False + for extension in az_json('extension list'): + if extension['name'] == 'application-insights': + app_insights_installed = True + + if not app_insights_installed: + p = ("The installed extension" + " 'application-insights' is in preview.") + try: + print('Installing application insights extension') + az('extension add --name application-insights') + except RaftAzCliException as ex: + if ex.error_message.strip() == p: + pass + else: + raise ex + + ai = az_json('monitor app-insights component create' + ' --resource-group' + f' {self.definitions.resource_group}' + f' --app {self.definitions.app_insights}' + f' --location {self.context["region"]}') + return { + 'app_id': ai['appId'], + 'instrumentation_key': ai['instrumentationKey'] + } + else: + print('Skipping AppInsights deployment') + return { + 'app_id': '', + 'instrumentation_key': '' + } + + def init_app_service_plan(self, sku): + print(f"Creating app service plan {self.definitions.asp}") + az('appservice plan create' + f' --name {self.definitions.asp}' + f' --resource-group {self.definitions.resource_group}' + f' --is-linux --location {self.context["region"]}' + f' --number-of-workers 2 --sku {sku}') + + def storage_account_connection_string(self, storage_account): + connection_string = az_json( + 'storage account show-connection-string' + f' --resource-group {self.definitions.resource_group}' + f' --name "{storage_account}"' + ' --query connectionString') + return connection_string + + def create_storage_connection_string_with_sas(self, storage_account): + print('Storage connection string with SAS' + f'{storage_account}') + + connection_string = self.storage_account_connection_string( + storage_account) + + sas_url = az_json( + 'storage account generate-sas' + ' --permissions acdlpruw --resource-types sco' + ' --expiry 2050-01-01' + ' --services t --https-only' + f' --account-name "{storage_account}"' + f' --connection-string "{connection_string}"') + + return (f"TableEndpoint=https://{storage_account}" + f".table.core.windows.net/;SharedAccessSignature={sas_url}") + + def container_image_name(self, registry_image_name): + return ( + f"{self.context['registry']}" + "/restapifuzztesting" + f"/{registry_image_name}:{self.definitions.container_tag}") + + def init_web_app_service( + self, service_name, + registry_image_name, registry_username, registry_password): + print('Creating') + print(f' {registry_image_name}') + + container_image_name = self.container_image_name(registry_image_name) + + if registry_username and registry_password: + app_service = az( + 'webapp create' + f' --name {service_name}' + f' --resource-group {self.definitions.resource_group}' + f' --plan {self.definitions.asp}' + f' --docker-registry-server-user {registry_username}' + f' --docker-registry-server-password {registry_password}' + f' --deployment-container-image-name {container_image_name}') + else: + app_service = az( + 'webapp create' + f' --name {service_name}' + f' --resource-group {self.definitions.resource_group}' + f' --plan {self.definitions.asp}' + f' --deployment-container-image-name {container_image_name}') + + print(' client-affinity & https') + + az('webapp update' + f' --name {service_name}' + f' --resource-group {self.definitions.resource_group}' + ' --client-affinity-enabled false --https-only true') + + def init_api_app_service( + self, service_bus, app_insights, + storage_connection_string_with_sas, sp, + container_registry_username, container_registry_password, + utils_file_share): + + self.init_web_app_service( + service_name=self.definitions.api_service_webapp, + registry_image_name='apiservice', + registry_username=container_registry_username, + registry_password=container_registry_password) + + rg = self.definitions.resource_group + event_domain = self.definitions.event_domain + domain = az_json('eventgrid domain show' + f' --resource-group {rg} --name {event_domain}') + keys = az_json('eventgrid domain key list' + f' --resource-group {rg} --name {event_domain}') + + endpoint = domain['endpoint'] + key = keys['key1'] + + print(' application settings') + + web_app_settings = [ + { + 'name': "RAFT_METRICS_APP_INSIGHTS_KEY", + 'slotSetting': False, + 'value': self.metrics_app_insights_key + }, + { + 'name': "RAFT_SITE_HASH", + 'slotSetting': False, + 'value': self.site_hash + }, + { + 'name': "RAFT_SERVICEBUS_SEND_CONNECTION_STRING", + 'slotSetting': False, + 'value': service_bus['send_sb_sas'] + }, + { + 'name': ("RAFT_SERVICEBUS_AGENT_" + "SEND_EVENTS_CONNECTION_STRING"), + 'slotSetting': False, + 'value': service_bus['send_events_sb_sas'] + }, + { + 'name': "RAFT_STORAGE_TABLE_CONNECTION_STRING", + 'slotSetting': False, + 'value': storage_connection_string_with_sas + }, + { + 'name': "APPINSIGHTS_INSTRUMENTATIONKEY", + 'slotSetting': False, + 'value': app_insights['instrumentation_key'] + }, + { + 'name': "RAFT_SERVICE_PRINCIPAL_CLIENT_ID", + 'slotSetting': False, + 'value': sp['appId'] + }, + { + 'name': "RAFT_SERVICE_PRINCIPAL_CLIENT_SECRET", + 'slotSetting': False, + 'value': sp['password'] + }, + { + 'name': "RAFT_SERVICE_PRINCIPAL_TENANT_ID", + 'slotSetting': False, + 'value': sp['tenant'] + }, + { + 'name': "RAFT_RESOURCE_GROUP_NAME", + 'slotSetting': False, + 'value': rg + }, + { + 'name': "RAFT_EVENT_DOMAIN", + 'slotSetting': False, + 'value': event_domain + }, + { + 'name': "RAFT_UTILS_FILESHARE", + 'slotSetting': False, + 'value': utils_file_share + }, + { + 'name': "RAFT_UTILS_SAS", + 'slotSetting': False, + 'value': self.storage_account_connection_string( + self.definitions.storage_utils) + }, + { + 'name': "RAFT_SERVICE_PRINCIPAL_SUBSCRIPTION_ID", + 'slotSetting': False, + 'value': self.definitions.subscription + } + ] + + settings_path = os.path.join(script_dir, 'webAppSettings.json') + with open(settings_path, 'w') as settings: + json.dump(web_app_settings, settings) + + az('webapp config appsettings set' + f' --resource-group {rg}' + f' --name {self.definitions.api_service_webapp}' + f' --settings "@{settings_path}"') + os.remove(settings_path) + + print(" enabling deployment updates" + " of web-app from Container Gallery") + az('webapp deployment container config --enable-cd true' + f' --name {self.definitions.api_service_webapp}' + f' --resource-group {rg}') + + def init_storage_account(self, storage_account): + print(f'Creating Storage Account: {storage_account}') + az('storage account create' + f' --name {storage_account}' + f' --resource-group {self.definitions.resource_group}' + f' --https-only true --location {self.context["region"]}') + + def init_file_storage(self, storage_account): + print(f'Creating FileShare Storage Account: {storage_account}') + az('storage account create' + f' --name {storage_account}' + f' --resource-group {self.definitions.resource_group}' + ' --sku Premium_ZRS --kind FileStorage' + f' --https-only true --location {self.context["region"]}') + + def init_service_principal( + self, name, subscription_id, + resource_group, assign_roles): + print('Creating') + print(f' service principal {name}') + + all_sps = az_json(f'ad sp list --display-name {name}') + + if len(all_sps) > 0: + existing_sp = all_sps[0] + else: + existing_sp = None + + if existing_sp: + app_id = existing_sp['appId'] + print(f' using Existing Service Principal with AppID: {app_id}') + + else: + # localhost is needed as a reply-url + # if the user is not connected via a VPN connection + login_url = ( + 'https://login.microsoftonline.com' + '/common/oauth2/nativeclient') + + while(True): + try: + app = az_json( + 'ad app create' + f' --display-name "{name}"' + ' --native-app true --reply-urls' + f' "{login_url}"' + ' "http://localhost"') + break + except RaftAzCliException as ex: + print(f"Got: {ex.error_message}") + print("Trying again...") + time.sleep(3.0) + + while not existing_sp: + print(' waiting for app registration to appear' + f' in AD with App ID: {app["appId"]}') + try: + existing_sp = az(f'ad app show --id {app["appId"]}') + except Exception: + time.sleep(5) + + sp = az_json(f'ad sp create --id {app["appId"]}') + print(f' service Principal AppID: {app["appId"]}') + app_id = app['appId'] + new_sp = [] + while len(new_sp) <= 0: + print(' waiting for service principal to appear' + f' in AD with App ID: {app["appId"]}') + try: + new_sp = az_json(f'ad sp list --display-name {name}') + except Exception: + time.sleep(5) + + for assign in assign_roles: + assign(app_id) + + az(f'ad sp update --id {app_id} --set appRoleAssignmentRequired=false') + sp = az_json(f'ad sp credential reset --append --name {app_id}') + + # Add command will write an informational message to stderr. + # The output to stderr should not be treated as error in this case. + try: + print(" adding Read permission") + user_read_permission = "e1fe6dd8-ba31-4d61-89e7-88639da4683d" + read = az('ad app permission add' + ' --api 00000003-0000-0000-c000-000000000000' + f' --id {app_id}' + f' --api-permissions "{user_read_permission}=Scope"') + except RaftAzCliException as ex: + if ex.error_message.startswith( + 'Invoking "az ad app permission grant' + f' --id {app_id}' + ' --api' + ' 00000003-0000-0000-c000-000000000000"' + ' is needed to make the change effective'): + + pass + else: + raise ex + + # The grant command fails, because of some bug. + # The command actually succeeds and the command is needed. + # So we don't use the az-z function because + # we want to continue even though it fails. + try: + print(' granting permissions') + az('ad app permission grant' + f' --id {app_id}' + ' --api 00000003-0000-0000-c000-000000000000') + except RaftAzCliException as ex: + if ex.error_message.startswith("Operation failed" + " with status: 'Bad Request'."): + pass + elif existing_sp: + pass + else: + raise ex + + return sp + + def init_test_infra( + self, service_bus, app_insights, + storage_connection_string_with_sas, + sp, container_registry_username, container_registry_password): + + print('Creating Storage Account: ' + f'{self.definitions.test_infra_storage}') + az('storage account create' + f' --name {self.definitions.test_infra_storage}' + f' --resource-group {self.definitions.resource_group}' + f' --https-only true --location {self.context["region"]}') + + print('Creating') + print(f' function resource {self.definitions.test_infra}') + rg = self.definitions.resource_group + + storage_account = self.definitions.test_infra_storage + + if self.context['useAppInsights']: + ai = f' --app-insights {self.definitions.app_insights}' + else: + ai = ' --disable-app-insights true' + + az_function = az('functionapp create' + f' --name {self.definitions.test_infra}' + f' --storage-account {storage_account}' + f' --resource-group {rg}' + f' --plan "{self.definitions.asp}"' + ' --functions-version 3' + ' --os-type Linux --runtime dotnet' + f' {ai}') + + connection_string = az_json( + 'storage account show-connection-string' + f' --resource-group {rg}' + f' --name {storage_account}' + ' --query connectionString' + ' --output json') + + test_infra_settings = [ + { + 'name': "AzureWebJobsStorage", + 'slotSetting': False, + 'value': connection_string + }, + { + 'name': "RAFT_APPINSIGHTS", + 'slotSetting': False, + 'value': app_insights['instrumentation_key'] + }, + { + 'name': "RAFT_STORAGE_TABLE_CONNECTION_STRING", + 'slotSetting': False, + 'value': storage_connection_string_with_sas + } + ] + + settings_path = os.path.join(script_dir, 'testInfraSettings.json') + with open(settings_path, 'w') as settings: + json.dump(test_infra_settings, settings) + + print(" settings") + az('functionapp config appsettings set' + f' --name {self.definitions.test_infra}' + f' --resource-group {rg}' + f' --settings "@{settings_path}"') + + os.remove(settings_path) + + print(" updating container registry settings") + container_image_name = self.container_image_name('test-infra-func') + + if container_registry_password and container_registry_username: + functionAppConfig = az( + 'functionapp config container set' + ' --docker-registry-server-url' + f' "{self.context["registry"]}"' + f' --docker-registry-server-user {container_registry_username}' + f' --docker-registry-server-password {container_registry_password}' + f' --name {self.definitions.test_infra}' + f' --resource-group {rg}' + f' --docker-custom-image-name "{container_image_name}"') + else: + functionAppConfig = az( + 'functionapp config container set' + ' --docker-registry-server-url' + f' "{self.context["registry"]}"' + f' --name {self.definitions.test_infra}' + f' --resource-group {rg}' + f' --docker-custom-image-name "{container_image_name}"') + + print(" Enabling deployment updates of test-infra" + "Azure Function from Container Gallery") + az('functionapp deployment container config --enable-cd true' + f' --name {self.definitions.test_infra}' + f' --resource-group {rg}') + + def init_orchestrator( + self, service_bus, app_insights, + storage_connection_string_with_sas, + sp, container_registry_username, container_registry_password, + utils_file_share): + print('Creating') + print(f' function resource {self.definitions.orchestrator}') + rg = self.definitions.resource_group + storage_account = self.definitions.storage_account + + if self.context['useAppInsights']: + ai = f' --app-insights {self.definitions.app_insights}' + else: + ai = ' --disable-app-insights true' + + az_function = az('functionapp create' + f' --name {self.definitions.orchestrator}' + f' --storage-account {storage_account}' + f' --resource-group {rg}' + f' --plan "{self.definitions.asp}"' + ' --functions-version 3' + ' --os-type Linux --runtime dotnet' + f' {ai}') + + connection_string = az_json( + 'storage account show-connection-string' + f' --resource-group {rg}' + f' --name {storage_account}' + ' --query connectionString' + ' --output json') + + domain = az_json( + 'eventgrid domain show' + f' --resource-group {rg}' + f' --name {self.definitions.event_domain}') + + keys = az_json( + 'eventgrid domain key list' + f' --resource-group {rg}' + f' --name {self.definitions.event_domain}') + + endpoint = domain['endpoint'] + key = keys['key1'] + + orchestrator_settings = [ + { + 'name': "AzureWebJobsStorage", + 'slotSetting': False, + 'value': connection_string + }, + { + 'name': "AzureWebJobsServiceBus", + 'slotSetting': False, + 'value': service_bus['read_sb_sas'] + }, + { + 'name': "RAFT_KEY_VAULT", + 'slotSetting': False, + 'value': self.definitions.key_vault + }, + { + 'name': "RAFT_SERVICE_PRINCIPAL_CLIENT_ID", + 'slotSetting': False, + 'value': sp['appId'] + }, + { + 'name': "RAFT_SERVICE_PRINCIPAL_CLIENT_SECRET", + 'slotSetting': False, + 'value': sp['password'] + }, + { + 'name': "RAFT_SERVICE_PRINCIPAL_TENANT_ID", + 'slotSetting': False, + 'value': sp['tenant'] + }, + { + 'name': "RAFT_SERVICE_PRINCIPAL_SUBSCRIPTION_ID", + 'slotSetting': False, + 'value': self.definitions.subscription + }, + { + 'name': "RAFT_CONTAINER_RUN_RESOURCE_GROUP", + 'slotSetting': False, + 'value': self.definitions.resource_group + }, + { + 'name': "RAFT_ORCHESTRATOR_STORAGE", + 'slotSetting': False, + 'value': self.definitions.storage_account + }, + { + 'name': "RAFT_UTILS_STORAGE", + 'slotSetting': False, + 'value': self.definitions.storage_utils + }, + { + 'name': "RAFT_RESULTS_STORAGE", + 'slotSetting': False, + #'value': self.definitions.storage_results + 'value': self.definitions.storage_account + }, + { + 'name': "RAFT_UTILS_FILESHARE", + 'slotSetting': False, + 'value': utils_file_share + }, + { + 'name': "RAFT_REPORT_JOB_STATUS", + 'slotSetting': False, + 'value': service_bus['send_sb_sas'] + }, + { + 'name': ("RAFT_SERVICEBUS_AGENT_" + "SEND_EVENTS_CONNECTION_STRING"), + 'slotSetting': False, + 'value': service_bus['send_events_sb_sas'] + }, + { + 'name': "RAFT_APPINSIGHTS", + 'slotSetting': False, + 'value': app_insights['instrumentation_key'] + }, + { + 'name': "RAFT_METRICS_APP_INSIGHTS_KEY", + 'slotSetting': False, + 'value': self.metrics_app_insights_key + }, + { + 'name': "RAFT_SITE_HASH", + 'slotSetting': False, + 'value': self.site_hash + }, + { + 'name': "RAFT_EVENT_GRID_ENDPOINT", + 'slotSetting': False, + 'value': endpoint + }, + { + 'name': "RAFT_EVENT_GRID_KEY", + 'slotSetting': False, + 'value': key + }, + { + 'name': "RAFT_STORAGE_TABLE_CONNECTION_STRING", + 'slotSetting': False, + 'value': storage_connection_string_with_sas + } + ] + + settings_path = os.path.join(script_dir, 'orchestratorSettings.json') + with open(settings_path, 'w') as settings: + json.dump(orchestrator_settings, settings) + + print(" settings") + az('functionapp config appsettings set' + f' --name {self.definitions.orchestrator}' + f' --resource-group {rg}' + f' --settings "@{settings_path}"') + + os.remove(settings_path) + + print(" updating container registry settings") + container_image_name = self.container_image_name('orchestrator') + + if container_registry_username and container_registry_password: + functionAppConfig = az( + 'functionapp config container set' + ' --docker-registry-server-url' + f' "{self.context["registry"]}"' + f' --docker-registry-server-user {container_registry_username}' + f' --docker-registry-server-password {container_registry_password}' + f' --name {self.definitions.orchestrator}' + f' --resource-group {rg}' + f' --docker-custom-image-name "{container_image_name}"') + else: + functionAppConfig = az( + 'functionapp config container set' + ' --docker-registry-server-url' + f' "{self.context["registry"]}"' + f' --name {self.definitions.orchestrator}' + f' --resource-group {rg}' + f' --docker-custom-image-name "{container_image_name}"') + + print(" Enabling deployment updates of orchestrator" + "Azure Function from Container Gallery") + az('functionapp deployment container config --enable-cd true' + f' --name {self.definitions.orchestrator}' + f' --resource-group {rg}') + + def init_event_grid_domain(self): + print('Creating') + event_domain = self.definitions.event_domain + print(f' event domain {event_domain}') + az('eventgrid domain create' + f' --location {self.context["region"]}' + f' --name {event_domain}' + f' --resource-group {self.definitions.resource_group}') + + def add_resource_providers(self): + print('Enabling container providers') + az("provider register" + " --namespace Microsoft.ContainerRegistry" + f" --subscription {self.definitions.subscription} --wait") + + az("provider register" + " --namespace Microsoft.ContainerInstance" + f" --subscription {self.definitions.subscription} --wait") + + def update_deployment_context(self): + print(f'Updating deployment context: {self.defaults_path}') + with open(self.defaults_path, 'w') as d: + defaults = self.context.copy() + defaults.pop('secret') + json.dump(defaults, d, indent=4) + + def test_az_version(self): + supported_versions = ['2.10.1', '2.12.0', '2.12.1', '2.13.0'] + # az sometimes reports the version with an asterisk. + # Perhaps when a new version of the CLI is available. + tested_az_cli_versions = ( + supported_versions + + list(map(lambda x: f"{x} *", supported_versions))) + current_version = az('--version') + + for line in current_version.splitlines(): + if 'azure-cli' in line: + v = line[len('azure-cli'):].strip() + if v not in tested_az_cli_versions: + print("---------------------------------------------") + print("WARNING: RUNNING DEPLOYMENT WITH VERSION OF" + f" AZ-CLI {v}. DEPLOYING SERVICE WAS NOT TESTED" + " WITH THIS VERSION.") + print(f"IF DEPLOYMENT FAILS. PLEASE USE ONE OF THE" + f" FOLLOWING AZ-CLI VERSIONS {supported_versions}") + print("---------------------------------------------") + else: + break + + def test_az_logged_in(self): + try: + accounts = az_json('account list') + except Exception: + raise Exception("Make sure that az is installed" + "before running service deployment") + + subscription_found = False + for account in accounts: + if account['id'] == self.context['subscription']: + subscription_found = True + break + + if not subscription_found: + raise Exception("It looks like your not logged in with az" + " to an account that contains the" + f" subscription {self.context['subscription']}" + " Please run 'az login' before" + " re-running this script.") + + def dos2unix(self, file_path): + print(f'Converting dos2unix {file_path}') + dos_file_path = file_path + ".dos" + os.rename(file_path, dos_file_path) + + with open(dos_file_path, 'rb') as dos_file: + file_contents = dos_file.read() + + with open(file_path, 'wb') as unix_file: + for line in file_contents.splitlines(): + unix_file.write(line + b'\n') + os.remove(dos_file_path) + + def convert_dir_dos2unix(self, folder_path): + for root_folder_path, dirs, files in os.walk(folder_path): + for file_name in files: + file_path = os.path.join(root_folder_path, file_name) + if pathlib.Path(file_path).suffix in dos2unix_file_types: + self.dos2unix(file_path) + + def upload_utils(self, file_share): + utils = os.path.join(f'{script_dir}', '..', 'raft-utils') + self.convert_dir_dos2unix(utils) + + connection_string = self.storage_account_connection_string( + self.definitions.storage_utils) + + exists = az_json('storage share exists' + f' --name {file_share}' + f' --connection-string "{connection_string}"') + + if exists['exists'] is True: + print(f'Uploading tools to an existing share {file_share}') + else: + print(f'Creating new file share {file_share}') + share = az_json('storage share create' + f' --name {file_share}' + f' --connection-string "{connection_string}"') + + upload = az('storage file upload-batch' + f' --connection-string "{connection_string}"' + f' --destination {file_share}' + f' --source {utils}' + f' --pattern "*"' + ' --validate-content') + + print('Updating orchestrator utils file share') + az('functionapp config appsettings set' + f' --name {self.definitions.orchestrator}' + f' --resource-group {self.definitions.resource_group}' + f' --settings "RAFT_UTILS_FILESHARE={file_share}"') + + print('Updating webapp utils file share') + az('functionapp config appsettings set' + f' --name {self.definitions.api_service_webapp}' + f' --resource-group {self.definitions.resource_group}' + f' --settings "RAFT_UTILS_FILESHARE={file_share}"') + return + + def deploy(self, sku, skip_sp_deployment): + if skip_sp_deployment and not ( + self.context.get('clientId') and + self.context.get('tenantId') and + self.context.get('secret')): + raise Exception('Only can skip Service Principal' + 'deployment when redeploying existing' + 'service and passing secret' + 'as deployment parameter') + + self.test_az_version() + self.test_az_logged_in() + + # if opt-out-from-metrics is not present, then assume that user + # is opt-in and patch the defaults.json with that + print(f'Creating deployment with hash {self.site_hash}') + az(f"account set --subscription {self.definitions.subscription}") + az("group create" + f" --name {self.definitions.resource_group}" + f" --location {self.context['region']}") + print(f"Deployment Resource Group: {self.definitions.resource_group}") + + self.init_key_vault() + + service_principal = {} + if skip_sp_deployment: + print('Skipping Service Principal deployment...') + service_principal['appId'] = self.context['clientId'] + service_principal['tenant'] = self.context['tenantId'] + service_principal['password'] = self.context['secret'] + else: + service_principal = self.init_service_principal( + self.definitions.deployment + "-raft", + self.definitions.subscription, + self.definitions.resource_group, + [self.assign_resource_group_roles, + self.assign_keyvault_roles]) + + # add service principal information to the keyvault + auth = { + 'client': service_principal['appId'], + 'tenant': service_principal['tenant'], + 'secret': service_principal['password'] + } + sp_path = os.path.join(tmp_dir, 'sp.json') + with open(sp_path, 'w') as sp_json: + json.dump(auth, sp_json) + + az('keyvault secret set' + f' --description "{self.definitions.deployment}' + ' Service Principal authentication credentials"' + f" --file {sp_path}" + ' --name RaftServicePrincipal' + f' --vault-name {self.definitions.key_vault}') + + try: + os.remove(sp_path) + except OSError: + pass + + if self.context.get('isPrivateRegistry'): + if 'getToken' in self.context: + print('Getting container registry token') + token_name = f"token-{self.site_hash}" + response = requests.get( + f"{self.context['getToken']}&name={token_name}") + if response.ok: + content = json.loads(response.text) + container_registry_username = content['tokenName'] + container_registry_password = content['password'] + else: + raise RaftApiException(response.text, response.status_code) + else: + container_registry_username = service_principal['appId'] + container_registry_password = service_principal['password'] + else: + container_registry_username = None + container_registry_password = None + + self.init_storage_account(self.definitions.storage_account) + sb_connection_strings = self.init_service_bus() + app_insights = self.init_app_insights() + storage_connection_string_with_sas = ( + self.create_storage_connection_string_with_sas( + self.definitions.storage_account)) + + self.init_storage_account(self.definitions.storage_utils) + #self.init_file_storage(self.definitions.storage_results) + + self.init_event_grid_domain() + + self.init_app_service_plan(sku) + tools_file_share = f'{uuid.uuid4()}' + + self.init_api_app_service( + sb_connection_strings, + app_insights, + storage_connection_string_with_sas, + service_principal, + container_registry_username, + container_registry_password, + tools_file_share) + + self.init_orchestrator( + sb_connection_strings, + app_insights, + storage_connection_string_with_sas, + service_principal, + container_registry_username, + container_registry_password, + tools_file_share) + + self.upload_utils(tools_file_share) + + if self.context.get('isDevelop') and not skip_sp_deployment: + self.init_test_infra( + sb_connection_strings, + app_insights, + storage_connection_string_with_sas, + service_principal, + container_registry_username, + container_registry_password) + + self.add_resource_providers() + + self.context['clientId'] = service_principal['appId'] + self.context['tenantId'] = service_principal['tenant'] + self.context['secret'] = service_principal['password'] + + self.update_deployment_context() + print('Waiting for service to start' + f' {self.definitions.api_service_webapp}') + self.wait_for_service_to_start() + print('Service started') + + def restart(self): + try: + pre_restart_info = self.service_info() + except RaftApiException: + pre_restart_info = None + + print(f'Restarting {self.definitions.orchestrator}') + az('functionapp restart' + f' --name {self.definitions.orchestrator}' + f' --resource-group {self.definitions.resource_group}') + + print(f'Restarting {self.definitions.api_service_webapp}') + az('webapp restart' + f' --name {self.definitions.api_service_webapp}' + f' --resource-group {self.definitions.resource_group}') + + if self.context.get('isDevelop'): + print(f'Restarting {self.definitions.test_infra}') + az('functionapp restart' + f' --name {self.definitions.test_infra}' + f' --resource-group {self.definitions.resource_group}') + + sys.stdout.write('Waiting for service to start') + self.wait_for_service_to_start(pre_restart_info) + print() + print('Done') + + def service_info(self): + raft_api = RestApiClient( + self.definitions.endpoint, + self.context['clientId'], + self.context['tenantId'], + self.context.get('secret')) + info = raft_api.get('/info') + if info.ok: + return json.loads(info.text) + else: + raise RaftApiException(info.text, info.status_code) + + def wait_for_service_to_start(self, old_info=None): + new_info = old_info + while True: + try: + new_info = self.service_info() + if old_info is None: + return + + new_t = new_info['serviceStartTime'] + old_t = old_info['serviceStartTime'] + if new_t != old_t: + return + except RaftApiException as ex: + print('Failed while waiting for service' + f' to start due to {ex.message}') + raise ex + except Exception: + new_info = old_info + time.sleep(3) + sys.stdout.write('.') + sys.stdout.flush() diff --git a/cli/raft_sdk/raft_service.py b/cli/raft_sdk/raft_service.py new file mode 100644 index 0000000..dc6fc3d --- /dev/null +++ b/cli/raft_sdk/raft_service.py @@ -0,0 +1,379 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import json +import os +import sys +import time + +import tabulate +from .raft_common import RaftApiException, RestApiClient, RaftDefinitions + +script_dir = os.path.dirname(os.path.abspath(__file__)) +dos2unix_file_types = [".sh", ".bash"] + + +class RaftJobConfig(): + def __init__(self, + *, + substitutions={}, + file_path=None, + json_config=None): + if file_path: + with open(file_path, 'r') as config_file: + c = config_file.read() + for src in substitutions: + c = c.replace(src, substitutions[src]) + config = json.loads(c) + self.config = config + elif json: + self.config = json_config + else: + raise Exception('Expected file_path or json to be set') + + def add_read_only_mount(self, file_share, mount_as): + fs = [{"FileShareName": file_share, "MountPath": mount_as}] + if 'readOnlyFileShareMounts' in self.config: + self.config['readOnlyFileShareMounts'] += fs + else: + self.config['readOnlyFileShareMounts'] = fs + + def add_read_write_mount(self, file_share, mount_as): + fs = [{"FileShareName": file_share, "MountPath": mount_as}] + if 'readWriteFileShareMounts' in self.config: + self.config['readWriteFileShareMounts'] += fs + else: + self.config['readWriteFileShareMounts'] = fs + + def add_read_only_mounts(self, read_only_mounts): + if 'readOnlyMounts' in self.config: + self.config['readOnlyFileShareMounts'] += read_only_mounts + else: + self.config['readOnlyFileShareMounts'] = read_only_mounts + + def add_read_write_mounts(self, read_write_mounts): + if 'readWriteFileShareMounts' in self.config: + self.config['readWriteFileShareMounts'] += read_write_mounts + else: + self.config['readWriteFileShareMounts'] = read_write_mounts + + def add_metadata(self, data): + if 'webhook' in self.config: + if 'metadata' in self.config['webhook']: + self.config['metadata'] += data + else: + self.config['metadata'] = data + + +class RaftJobError(Exception): + def __init__(self, error, message): + self.error = error + self.message = message + + +class RaftCLI(): + def __init__(self, context=None): + if context: + self.context = context + else: + with open(os.path.join( + script_dir, + '..', + 'defaults.json'), 'r') as defaults_json: + self.context = json.load(defaults_json) + + self.definitions = RaftDefinitions(self.context) + self.raft_api = RestApiClient( + self.definitions.endpoint, + self.context['clientId'], + self.context['tenantId'], + self.context.get('secret')) + + def result_url(self, job_id): + ''' + Constructs Azure File Storage results URL + + Parameters: + job_id: job ID + + Returns: + URL that contains results of the job run + ''' + return( + "https://ms.portal.azure.com/#blade/Microsoft_Azure_FileStorage/" + "FileShareMenuBlade/overview/storageAccountId/" + f"%2Fsubscriptions%2F{self.definitions.subscription}" + f"%2FresourceGroups%2F{self.definitions.resource_group}" + f"%2Fproviders%2FMicrosoft.Storage%2FstorageAccounts%2F" + f"{self.definitions.storage_account}/" + f"path/{job_id}/protocol/") + + def job_status(self, job_id): + ''' + Gets job status + + Parameters: + job_id: job ID + + Returns: + Job status + ''' + response = self.raft_api.get(f'/jobs/{job_id}') + if response.ok: + return json.loads(response.text) + else: + raise RaftApiException(response.text, response.status_code) + + def list_jobs(self, time_span=None): + ''' + List jobs for specified look-back timespan + + Parameters: + time_span: look-back timespan. + Default is 24 hours + + Returns: + List of job status objects within 'now' minus 'timespan' + time window + ''' + if time_span: + response = self.raft_api.get( + f'/jobs?timeSpanFilter={time_span}') + else: + response = self.raft_api.get(f'/jobs') + if response.ok: + return json.loads(response.text) + else: + raise RaftApiException(response.text, response.status_code) + + def new_job(self, job_config, region=None): + ''' + Creates and deploys a new job with specified job configuration + + Parameters: + job_config: job configuration + + region: if set, then deploy job to that region + + Returns: + Job ID assigned to newly created job + ''' + if region: + query = f'/jobs?region={region}' + else: + query = '/jobs' + response = self.raft_api.post(query, job_config.config) + if response.ok: + return json.loads(response.text) + else: + raise RaftApiException(response.text, response.status_code) + + def update_job(self, job_id, job_config): + ''' + Re-apply job configuration on an existing job. + This is useful when one of the job tasks has isIdling flag set + to 'true' + + Parameters: + job_id: currently running job + job_config: job configuration to apply to the job + ''' + response = self.raft_api.post(f'/jobs/{job_id}', job_config.config) + if response.ok: + return json.loads(response.text) + else: + raise RaftApiException(response.text, response.status_code) + + def delete_job(self, job_id): + ''' + Deletes job + + Parameters: + job_id: ID of a job to delete + ''' + response = self.raft_api.delete(f'/jobs/{job_id}') + if response.ok: + return json.loads(response.text) + else: + raise RaftApiException(response.text, response.status_code) + + def list_available_webhooks_events(self): + ''' + Lists available webhook events + + Returns: + list of events that are used with + other webhook API calls + ''' + response = self.raft_api.get('/webhooks/events') + if response.ok: + return json.loads(response.text) + else: + raise RaftApiException(response.text, response.status_code) + + def set_webhooks_subscription(self, name, event, url): + ''' + Creates or updates webhook subscription + + Parameters: + name: webhook name + event: one of the events returned by + list_available_webhooks_events + url: URL to POST webhook data to + + Returns: + webhook configuration + ''' + data = { + 'WebhookName': name, + 'Event': event, + 'TargetUrl': url + } + response = self.raft_api.post('/webhooks', data) + if response.ok: + return json.loads(response.text) + else: + raise RaftApiException(response.text, response.status_code) + + def test_webhook(self, name, event): + ''' + Tests webhook by posting dummy data to the webhook + registered with set_webhooks_subscription + + Parameters: + name: webhook name + event: one of the events returned by + list_available_webhooks_events + + Returns: + Webhook send status + ''' + response = self.raft_api.put(f'/webhooks/test/{name}/{event}', None) + if response.ok: + return json.loads(response.text) + else: + raise RaftApiException(response.text, response.status_code) + + def list_webhooks(self, name, event=None): + ''' + Lists webhook registrations + + Parameters: + name: webhook name + event: one of the events returned by + list_available_webhooks_events + if None then list webhooks for all events + + Returns: + List of webhook definitions + ''' + if event: + url = f'/webhooks?name={name}&event={event}' + else: + url = f'/webhooks?name={name}' + + response = self.raft_api.get(url) + if response.ok: + return json.loads(response.text) + else: + raise RaftApiException(response.text, response.status_code) + + def delete_webhook(self, name, event): + ''' + Deletes webhook registration for the event + + Parameters: + name: webhook name + event: one of the events returned by + list_available_webhooks_events + ''' + response = self.raft_api.delete(f'/webhooks/{name}/{event}') + if response.ok: + return json.loads(response.text) + else: + raise RaftApiException(response.text, response.status_code) + + def print_status(self, status): + ''' + Prints status object to standard output in a readable format + + Parameters: + status: status object returned by the service + ''' + for s in status: + if s['agentName'] == s['jobId']: + print(f"{s['jobId']} {s['state']}") + if s.get('details') and len(s['details']) > 0: + details = '\n'.join(s['details']) + print("Details:") + print(f"{details}") + + for s in status: + if s['agentName'] != s['jobId']: + agent_status = ( + f"Agent: {s['agentName']}" + f" Tool: {s['tool']}" + f" State: {s['state']}") + + if 'metrics' in s: + metrics = s['metrics'] + total_request_counts = metrics.get('totalRequestCount') + if total_request_counts and total_request_counts > 0: + print(f"{agent_status}" + " Total Request Count:" + f" {total_request_counts}") + response_code_counts = [] + for key in metrics['responseCodeCounts']: + response_code_counts.append( + [key, metrics['responseCodeCounts'][key]]) + table = tabulate.tabulate( + response_code_counts, + headers=['Response Code', 'Count']) + print(table) + print() + else: + print(agent_status) + + if s.get('details') and len(s['details']) > 0: + details = '\n'.join(s['details']) + print("Details:") + print(f"{details}") + + def poll(self, job_id, poll_interval=10): + ''' + Polls and prints job status updates until job terminates. + + Parameters: + job_id: job id + poll_interval: poll interval in seconds + ''' + og_status = None + while True: + i = 0 + while i < poll_interval: + time.sleep(1) + sys.stdout.write('.') + sys.stdout.flush() + i += 1 + + try: + status = self.job_status(job_id) + if og_status != status: + og_status = status + print() + self.print_status(status) + for s in status: + # overall job status information + if s['agentName'] == s['jobId']: + completed = s['state'] == 'Completed' + stopped = s['state'] == 'ManuallyStopped' + error = s['state'] == 'Error' + timed_out = s['state'] == 'TimedOut' + if completed or stopped: + return + elif error or timed_out: + raise RaftJobError(s['state'], s['details']) + except RaftApiException as ex: + if ex.status_code != 404: + print(f"{ex.message}") + raise RaftApiException(ex.text, ex.status_code) diff --git a/cli/requirements.txt b/cli/requirements.txt new file mode 100644 index 0000000..2d2cf83 --- /dev/null +++ b/cli/requirements.txt @@ -0,0 +1,3 @@ +msal~=1.4.3 +requests~=2.24.0 +tabulate~=0.8.7 diff --git a/cli/samples/60/raft-restler.py b/cli/samples/60/raft-restler.py new file mode 100644 index 0000000..1ae57e6 --- /dev/null +++ b/cli/samples/60/raft-restler.py @@ -0,0 +1,74 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import pathlib +import sys +import os +import json +import urllib.parse +import copy +import random + +cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(cur_dir, '..', '..')) +from raft_sdk.raft_service import RaftCLI, RaftJobConfig + +def run(compile, test, host): + cli = RaftCLI() + substitutions = { + '{host}': host + } + compile_job_config = RaftJobConfig(file_path=compile, substitutions=substitutions) + + compile_task = compile_job_config.config['tasks'][0] + #use first task as template and create 30 compile task + compile_tasks = [] + for t in range(30): + new_task = copy.deepcopy(compile_task) + new_task['outputFolder'] = compile_task['outputFolder'] + f"-{t}" + new_task['toolConfiguration']['compileConfiguration']['mutationsSeed'] = random.randint(0, 1000) + compile_tasks.append(new_task) + + compile_job_config.config['tasks'] = compile_tasks + + print('Compile') + # create a new job with the Compile config and get new job ID + # in compile_job + compile_job = cli.new_job(compile_job_config) + # wait for a job with ID from compile_job to finish the run + cli.poll(compile_job['jobId']) + + substitutions['{compile.jobId}'] = compile_job['jobId'] + + print('Test') + test_job_config = RaftJobConfig(file_path=test, substitutions=substitutions) + + task_test_fuzz_lean = test_job_config.config['tasks'][0] + task_test = test_job_config.config['tasks'][1] + test_tasks = [] + for t in range(30): + new_task_test = copy.deepcopy(task_test) + new_task_test_fuzz_lean = copy.deepcopy(task_test_fuzz_lean) + + new_task_test['outputFolder'] = task_test['outputFolder'] + f"-{t}" + new_task_test['toolConfiguration']['runConfiguration']['inputFolderPath'] += '/' + compile_tasks[t]['outputFolder'] + + new_task_test_fuzz_lean['outputFolder'] = task_test_fuzz_lean['outputFolder'] + f"-{t}" + new_task_test_fuzz_lean['toolConfiguration']['runConfiguration']['inputFolderPath'] += '/' + compile_tasks[t]['outputFolder'] + + test_tasks.append(new_task_test) + test_tasks.append(new_task_test_fuzz_lean) + + test_job_config.config['tasks'] = test_tasks + test_job = cli.new_job(test_job_config) + cli.poll(test_job['jobId']) + +if __name__ == "__main__": + if len(sys.argv) != 2: + print('Please provide host under test as an argument that will be used to\ +substitute {sample.host} in compile.json and fuzz.json config files') + else: + host = sys.argv[1] + run(os.path.join(cur_dir, "raft.restler.compile.json"), + os.path.join(cur_dir, "raft.restler.test.json"), + host) \ No newline at end of file diff --git a/cli/samples/60/raft.restler.compile.json b/cli/samples/60/raft.restler.compile.json new file mode 100644 index 0000000..25b736e --- /dev/null +++ b/cli/samples/60/raft.restler.compile.json @@ -0,0 +1,42 @@ +{ + "swaggerLocation": { + "URL" : "https://{host}/swagger/v1/swagger.json" + }, + "resources" : { + "Cores" : 2, + "MemoryGBs" : 3 + }, + "rootFileShare" : "60-compile", + "tasks": [ + { + "toolName": "RESTler", + "outputFolder" : "RESTler-compile", + "isIdling": false, + + "toolConfiguration": { + "task": "compile", + "compileConfiguration": { + "useRefreshableToken": true, + "customDictionary": { + "customPayload": { + "duration": ["00:10:00"], + "swaggerLocation": ["{\"URL\": \"https://some.service.azurewebsites.net/swagger.json\"}"], + "authenticationMethod": ["{\"CommandLine\": \"abc\" }"], + "targetUrl":["{replace-with-valid-webhook-URL}"], + "event": ["JobStatus"], + "timeSpanFilter": ["00:10:00"], + "eventName": ["JobStatus"] + } + } + } + } + } + + + + + + + + ] +} diff --git a/cli/samples/60/raft.restler.test.json b/cli/samples/60/raft.restler.test.json new file mode 100644 index 0000000..abd995b --- /dev/null +++ b/cli/samples/60/raft.restler.test.json @@ -0,0 +1,48 @@ +{ + "swaggerLocation": { + "URL" : "https://{host}/swagger/v1/swagger.json" + }, + "host": "{host}", + "resources" : { + "Cores" : 4, + "MemoryGBs" : 12 + }, + "ReadOnlyFileShareMounts" : [ + { + "fileShareName" : "60-compile", + "mountPath" : "/job-compile" + } + ], + "tasks": [ + { + "toolName" : "RESTler", + "outputFolder": "RESTLer-test-fuzz-lean", + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + + "toolConfiguration" : { + "task": "TestFuzzLean", + "runConfiguration": { + "inputFolderPath": "/job-compile/{compile.jobId}", + "authenticationTokenRefreshIntervalSeconds": 300 + } + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-test", + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + "toolConfiguration" : { + "task": "Test", + "runConfiguration": { + "inputFolderPath": "/job-compile/{compile.jobId}" + } + } + } + ] +} diff --git a/cli/samples/combined-raft-and-no-authentication-sample/combined.py b/cli/samples/combined-raft-and-no-authentication-sample/combined.py new file mode 100644 index 0000000..bd62739 --- /dev/null +++ b/cli/samples/combined-raft-and-no-authentication-sample/combined.py @@ -0,0 +1,40 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import pathlib +import sys +import os +import json +import urllib.parse + +cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(cur_dir, '..', '..')) +import raft + +def run(compile, fuzz, sample_host): + cli = raft.RaftCLI() + subs = { + '{sample.host}' : sample_host, + '{defaults.deploymentName}' : cli.definitions.deployment + + } + compile_job_config = raft.RaftJobConfig(file_path=compile, substitutions=subs) + print('Compile') + compile_job = cli.new_job(compile_job_config) + cli.poll(compile_job['jobId']) + subs['{compile.jobId}'] = compile_job['jobId'] + + fuzz_job_config = raft.RaftJobConfig(file_path=fuzz, substitutions=subs) + print('Fuzz') + fuzz_job = cli.new_job(fuzz_job_config) + cli.poll(fuzz_job['jobId']) + +if __name__ == "__main__": + if len(sys.argv) != 2: + print('Please provide host under test as an argument that will be used to\ +substitute {sample.host} in compile.json and fuzz.json config files') + else: + host = sys.argv[1] + run(os.path.join(cur_dir, "compile.json"), + os.path.join(cur_dir, "fuzz.json"), + host) \ No newline at end of file diff --git a/cli/samples/combined-raft-and-no-authentication-sample/compile.json b/cli/samples/combined-raft-and-no-authentication-sample/compile.json new file mode 100644 index 0000000..75f997c --- /dev/null +++ b/cli/samples/combined-raft-and-no-authentication-sample/compile.json @@ -0,0 +1,31 @@ +{ + "swaggerLocation": { + "URL" : "https://{defaults.deploymentName}-raft-apiservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "tasks": [ + { + "toolName" : "RESTler", + "isIdling": false, + "outputFolder" : "{defaults.deploymentName}-compile", + + "toolConfiguration" : { + "task": "Compile", + "compileConfiguration": { + "useRefreshableToken": true + } + } + }, + + { + "toolName" : "RESTler", + "isIdling": false, + "outputFolder": "sample-compile", + "toolConfiguration" : { + "task": "Compile" + }, + "swaggerLocation": { + "URL": "https://{sample.host}/swagger/v1/swagger.json" + } + } + ] +} diff --git a/cli/samples/combined-raft-and-no-authentication-sample/fuzz.json b/cli/samples/combined-raft-and-no-authentication-sample/fuzz.json new file mode 100644 index 0000000..c79242d --- /dev/null +++ b/cli/samples/combined-raft-and-no-authentication-sample/fuzz.json @@ -0,0 +1,109 @@ +{ + "swaggerLocation": { + "URL" : "https://{defaults.deploymentName}-raft-apiservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "host": "{defaults.deploymentName}-raft-apiservice.azurewebsites.net", + "ReadOnlyFileShareMounts" : [ + { + "FileShareName" : "{compile.jobId}", + "MountPath" : "/job-compile" + } + ], + "resources" : { + "Cores" : 4, + "MemoryGBs" : 4 + }, + "tasks": [ + { + "duration": "00:20:00", + "toolName" : "RESTler", + "outputFolder" : "{defaults.deploymentName}-RESTler-fuzz", + "isIdling" : false, + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + "toolConfiguration" : { + "task": "Fuzz", + "runConfiguration": { + "inputFolderPath": "/job-compile/{defaults.deploymentName}-compile", + "useSsl": true, + "producerTimingDelay": 5 + } + } + }, + { + "isIdling" : false, + "toolName": "ZAP", + "keyVaultSecrets" : ["RaftServicePrincipal"], + "outputFolder": "{defaults.deploymentName}-ZAP-out", + + "authenticationMethod": { + "MSAL" : "RaftServicePrincipal" + } + }, + + { + "swaggerLocation": { + "URL" : "https://{sample.host}/swagger/v1/swagger.json" + }, + "host": "{sample.host}", + "isIdling" : false, + "toolName": "ZAP", + "outputFolder": "sample-zap-out" + }, + + { + "duration": "00:10:00", + "toolName" : "RESTler", + + "swaggerLocation": { + "URL" : "https://{sample.host}/swagger/v1/swagger.json" + }, + "host": "{sample.host}", + "outputFolder": "sample-RESTler-fuzz", + + "toolConfiguration" : { + "task": "Fuzz", + "runConfiguration": { + "inputFolderPath": "/job-compile/sample-compile" + } + } + }, + { + "duration": "00:10:00", + "toolName" : "RESTler", + + "swaggerLocation": { + "URL" : "https://{sample.host}/swagger/v1/swagger.json" + }, + "host": "{sample.host}", + "outputFolder": "sample-RESTler-fuzz-random-walk", + + "toolConfiguration" : { + "task": "FuzzRandomWalk", + "runConfiguration": { + "inputFolderPath": "/job-compile/sample-compile" + } + } + }, + { + "duration": "00:10:00", + "toolName" : "RESTler", + + "swaggerLocation": { + "URL" : "https://{sample.host}/swagger/v1/swagger.json" + }, + "host": "{sample.host}", + "outputFolder": "sample-RESTler-fuzz-bfs-cheap", + + "toolConfiguration" : { + "task": "FuzzBfsCheap", + "runConfiguration": { + "inputFolderPath": "/job-compile/sample-compile" + } + } + } + + ] +} diff --git a/cli/samples/no-authentication-sample-common-file-share/run-sample.py b/cli/samples/no-authentication-sample-common-file-share/run-sample.py new file mode 100644 index 0000000..857b3c1 --- /dev/null +++ b/cli/samples/no-authentication-sample-common-file-share/run-sample.py @@ -0,0 +1,50 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import pathlib +import sys +import os + +cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(cur_dir, '..', '..')) +from raft_sdk.raft_service import RaftCLI, RaftJobConfig + +def run(compile, fuzz, sample_host): + # instantiate RAFT CLI + cli = RaftCLI() + substitutions = { + '{sample.host}' : sample_host + } + # Create compilation step job configuratin + compile_job_config = RaftJobConfig(file_path = compile, substitutions=substitutions) + # add webhook metadata that will be included in every triggered webhook by Compile job + compile_job_config.add_metadata({"branch":"wizbangFeature"}) + + print('Compile') + # create a new job with the Compile config and get new job ID + # in compile_job + compile_job = cli.new_job(compile_job_config) + + # wait for a job with ID from compile_job to finish the run + cli.poll(compile_job['jobId']) + + substitutions['{compile.jobId}'] = compile_job['jobId'] + # create a new job config with Fuzz configuration JSON + fuzz_job_config = RaftJobConfig(file_path = fuzz, substitutions=substitutions) + print('Fuzz') + # add webhook metadata that will included in every triggered webhook by Fuzz job + fuzz_job_config.add_metadata({"branch":"wizbangFeature"}) + # create new fuzz job configuration + fuzz_job = cli.new_job(fuzz_job_config) + # wait for job ID from fuzz_job to finish the run + cli.poll(fuzz_job['jobId']) + +if __name__ == "__main__": + if len(sys.argv) != 2: + print('Please provide host under test as an argument that will be used to\ +substitute {sample.host} in compile.json and fuzz.json config files') + else: + host = sys.argv[1] + run(os.path.join(cur_dir, "sample.restler.compile.json"), + os.path.join(cur_dir, "sample.restler.fuzz.json"), + host) \ No newline at end of file diff --git a/cli/samples/no-authentication-sample-common-file-share/sample.restler.compile.json b/cli/samples/no-authentication-sample-common-file-share/sample.restler.compile.json new file mode 100644 index 0000000..1f46cb6 --- /dev/null +++ b/cli/samples/no-authentication-sample-common-file-share/sample.restler.compile.json @@ -0,0 +1,33 @@ +{ + "swaggerLocation": { + "URL": "https://{sample.host}/swagger/v1/swagger.json" + }, + "host": "{sample.host}", + "namePrefix" : "sample-compile-", + "rootFileshare" : "sample", + "webhook" : { + "name" : "sample-compile", + "metadata" : {} + }, + "tasks": [ + { + "toolName" : "RESTler", + "isIdling": false, + "outputFolder": "RESTler-compile-1", + "toolConfiguration" : { + "task": "Compile" + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-compile-2", + "toolConfiguration" : { + "task": "Compile", + "compileConfiguration": { + "mutationsSeed": 34534798 + } + } + } + + ] +} diff --git a/cli/samples/no-authentication-sample-common-file-share/sample.restler.fuzz.json b/cli/samples/no-authentication-sample-common-file-share/sample.restler.fuzz.json new file mode 100644 index 0000000..302252b --- /dev/null +++ b/cli/samples/no-authentication-sample-common-file-share/sample.restler.fuzz.json @@ -0,0 +1,48 @@ +{ + "swaggerLocation": { + "URL" : "https://{sample.host}/swagger/v1/swagger.json" + }, + "duration": "00:10:00", + "host": "{sample.host}", + "rootFileshare" : "sample", + "webhook" : { + "name" : "sample-fuzz", + "metadata" : {} + }, + "readOnlyFileShareMounts" : [{ + "FileShareName" : "sample", + "MountPath" : "/compile-out" + }], + "tasks": [ + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-fuzz-1", + "toolConfiguration" : { + "task": "Fuzz", + "runConfiguration": { + "inputFolderPath": "/compile-out/{compile.jobId}/RESTler-compile-1" + } + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-fuzz-2", + "toolConfiguration" : { + "task": "Fuzz", + "runConfiguration": { + "inputFolderPath": "/compile-out/{compile.jobId}/RESTler-Compile-1" + } + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-fuzz-3", + "toolConfiguration" : { + "task": "FuzzRandomWalk", + "runConfiguration": { + "inputFolderPath": "/compile-out/{compile.jobId}/RESTler-compile-2" + } + } + } + ] +} diff --git a/cli/samples/no-authentication-sample/run-sample.py b/cli/samples/no-authentication-sample/run-sample.py new file mode 100644 index 0000000..9349061 --- /dev/null +++ b/cli/samples/no-authentication-sample/run-sample.py @@ -0,0 +1,57 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import pathlib +import sys +import os + +cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(cur_dir, '..', '..')) +from raft_sdk.raft_service import RaftCLI, RaftJobConfig + +def run(compile, fuzz, host): + # instantiate RAFT CLI + cli = RaftCLI() + + # will replace {sample.host} with the value of host variable + # see sample.restler.compile.json and sample.restler.fuzz.json + subs = { + '{sample.host}' : host + } + # Create compilation job configuration + compile_job_config = RaftJobConfig(file_path=compile, substitutions=subs) + # add webhook metadata that will be included in every triggered webhook by Compile job + compile_job_config.add_metadata({"branch":"wizbangFeature"}) + print('Compile') + + # submit a new job with the Compile config and get new job ID + compile_job = cli.new_job(compile_job_config) + + # wait for a job with ID from compile_job to finish the run + cli.poll(compile_job['jobId']) + + # use compile job as input for fuzz job + subs['{compile.jobId}'] = compile_job['jobId'] + + # create a new job config with Fuzz configuration JSON + fuzz_job_config = RaftJobConfig(file_path=fuzz, substitutions=subs) + print('Fuzz') + # add webhook metadata that will included in every triggered webhook by Fuzz job + fuzz_job_config.add_metadata({"branch":"wizbangFeature"}) + # create new fuzz job configuration + fuzz_job = cli.new_job(fuzz_job_config) + + # wait for job ID from fuzz_job to finish the run + cli.poll(fuzz_job['jobId']) + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print('Please provide host under test as an argument that will be used to\ +substitute {sample.host} in compile.json and fuzz.json config files') + else: + host = sys.argv[1] + + run(os.path.join(cur_dir, "sample.restler.compile.json"), + os.path.join(cur_dir, "sample.restler.fuzz.json"), + host) \ No newline at end of file diff --git a/cli/samples/no-authentication-sample/sample.restler.compile.json b/cli/samples/no-authentication-sample/sample.restler.compile.json new file mode 100644 index 0000000..0cc5d6c --- /dev/null +++ b/cli/samples/no-authentication-sample/sample.restler.compile.json @@ -0,0 +1,30 @@ +{ + "swaggerLocation": { + "URL": "https://{sample.host}/swagger/v1/swagger.json" + }, + "namePrefix" : "sample-compile-", + "webhook" : { + "name" : "sample-compile", + "metadata" : {} + }, + "tasks": [ + { + "toolName" : "RESTler", + "isIdling": false, + "outputFolder": "compile-1", + "toolConfiguration" : { + "task": "Compile" + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "compile-2", + "toolConfiguration" :{ + "task": "Compile", + "compileConfiguration": { + "mutationsSeed": 34534798 + } + } + } + ] +} diff --git a/cli/samples/no-authentication-sample/sample.restler.fuzz.json b/cli/samples/no-authentication-sample/sample.restler.fuzz.json new file mode 100644 index 0000000..9eef853 --- /dev/null +++ b/cli/samples/no-authentication-sample/sample.restler.fuzz.json @@ -0,0 +1,50 @@ +{ + "swaggerLocation": { + "URL": "https://{sample.host}/swagger/v1/swagger.json" + }, + "host": "{sample.host}", + "duration": "00:10:00", + "rootFileshare" : "sample-fuzz", + "webhook" : { + "name" : "sample-fuzz", + "metadata" : {} + }, + "readonlyFileShareMounts" : [ + { + "FileShareName" : "{compile.jobId}", + "MountPath" : "/job-compile" + } + ], + "tasks": [ + { + "toolName" : "RESTler", + "outputFolder" : "fuzz-1", + "toolConfiguration" : { + "task": "Fuzz", + "runConfiguration": { + "inputFolderPath": "/job-compile/compile-1" + } + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "fuzz-2", + "toolConfiguration" : { + "task": "Fuzz", + "runConfiguration": { + "inputFolderPath": "/job-compile/compile-1" + } + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "fuzz-3", + "toolConfiguration" : { + "task": "Fuzz", + "runConfiguration": { + "inputFolderPath": "/job-compile/compile-2" + } + } + } + ] +} diff --git a/cli/samples/no-authentication-sample/sample.restler.replay.json b/cli/samples/no-authentication-sample/sample.restler.replay.json new file mode 100644 index 0000000..1fb748d --- /dev/null +++ b/cli/samples/no-authentication-sample/sample.restler.replay.json @@ -0,0 +1,24 @@ +{ + "swaggerLocation": { + "URL": "https://{sample.host}/swagger/v1/swagger.json" + }, + "host": "{sample.host}", + "readOnlyFileShareMounts" : [ + { + "FileShareName" : "sample-fuzz", + "MountPath" : "/job-run" + } + ], + "tasks": [ + { + "toolName" : "RESTler", + "toolConfiguration" : { + "outputFolder" : "RESTler-replay", + "task": "Replay", + "runConfiguration": { + "inputFolderPath": "/job-run/{fuzz.jobId}/fuzz-1" + } + } + } + ] +} diff --git a/cli/samples/no-authentication-sample/sample.zap.json b/cli/samples/no-authentication-sample/sample.zap.json new file mode 100644 index 0000000..26985c9 --- /dev/null +++ b/cli/samples/no-authentication-sample/sample.zap.json @@ -0,0 +1,13 @@ +{ + "swaggerLocation": { + "URL" : "https://{sample.host}/swagger/v1/swagger.json" + }, + "host": "{sample.host}", + "tasks": [ + { + "isIdling" : false, + "toolName": "ZAP", + "outputFolder" : "zap-out" + } + ] +} diff --git a/cli/samples/raft-common-file-share/raft-restler-replay.py b/cli/samples/raft-common-file-share/raft-restler-replay.py new file mode 100644 index 0000000..c22dea2 --- /dev/null +++ b/cli/samples/raft-common-file-share/raft-restler-replay.py @@ -0,0 +1,48 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import pathlib +import sys +import os +import json +import urllib.parse + +cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(cur_dir, '..', '..')) +from raft_sdk.raft_service import RaftCLI, RaftJobConfig + +def run(replay, fuzz_job_id, replay_job_id=None): + cli = RaftCLI() + substitutions = { + '{defaults.deploymentName}': cli.definitions.deployment, + '{jobRunId}' : fuzz_job_id + } + replay_job_config = RaftJobConfig(file_path=replay, substitutions=substitutions) + + print('Replay') + isIdle = False + for task in replay_job_config.config['tasks']: + isIdle = isIdle or task['isIdling'] + + if isIdle and replay_job_id: + cli.update_job(replay_job_id, replay_job_config) + print(f'Idle Job: {replay_job_id}') + else: + # create new fuzz job configuration + replay_job_id = cli.new_job(replay_job_config) + if isIdle: + print(f'New Idle Job: {replay_job_id}') + else: + print(f'New Job: {replay_job_id}') + + if not isIdle: + # wait for job ID from fuzz_job to finish the run + cli.poll(replay_job_id['jobId']) + + +if __name__ == "__main__": + run(replay = "raft.restler.replay.json", + #job ID that produced bugs and those bugs going to be replayed + fuzz_job_id = "d29c7a2a-1815-4edb-91c1-56dd4faea0ce", + replay_job_id=None) + \ No newline at end of file diff --git a/cli/samples/raft-common-file-share/raft-restler.py b/cli/samples/raft-common-file-share/raft-restler.py new file mode 100644 index 0000000..24f955c --- /dev/null +++ b/cli/samples/raft-common-file-share/raft-restler.py @@ -0,0 +1,42 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import pathlib +import sys +import os +import json +import urllib.parse + +cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(cur_dir, '..', '..')) +from raft_sdk.raft_service import RaftCLI, RaftJobConfig + +def run(compile, test, fuzz): + # instantiate RAFT CLI + cli = RaftCLI() + substitutions = { + '{defaults.deploymentName}': cli.definitions.deployment + } + compile_job_config = RaftJobConfig(file_path=compile, substitutions=substitutions) + print('Compile') + # create a new job with the Compile config and get new job ID + # in compile_job + compile_job = cli.new_job(compile_job_config) + # wait for a job with ID from compile_job to finish the run + cli.poll(compile_job['jobId']) + substitutions['{compile.jobId}'] = compile_job['jobId'] + + print('Test') + test_job_config = RaftJobConfig(file_path=test, substitutions=substitutions) + test_job = cli.new_job(test_job_config) + cli.poll(test_job['jobId']) + + print('Fuzz') + fuzz_job_config = RaftJobConfig(file_path=fuzz, substitutions=substitutions) + fuzz_job = cli.new_job(fuzz_job_config) + cli.poll(fuzz_job['jobId']) + +if __name__ == "__main__": + run(os.path.join(cur_dir, "raft.restler.compile.json"), + os.path.join(cur_dir, "raft.restler.test.json"), + os.path.join(cur_dir, "raft.restler.fuzz.json")) \ No newline at end of file diff --git a/cli/samples/raft-common-file-share/raft-zap.py b/cli/samples/raft-common-file-share/raft-zap.py new file mode 100644 index 0000000..3b1faed --- /dev/null +++ b/cli/samples/raft-common-file-share/raft-zap.py @@ -0,0 +1,25 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import pathlib +import sys +import os +import json +import urllib.parse + +cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(cur_dir, '..', '..')) +from raft_sdk.raft_service import RaftCLI, RaftJobConfig + +def run(run_zap): + cli = RaftCLI() + substitutions = { + '{defaults.deploymentName}': cli.definitions.deployment + } + run_zap_config = RaftJobConfig(file_path=run_zap, substitutions=substitutions) + zap_job = cli.new_job(run_zap_config) + print(zap_job) + cli.poll(zap_job['jobId']) + +if __name__ == "__main__": + run("raft.zap.json") \ No newline at end of file diff --git a/cli/samples/raft-common-file-share/raft.restler.compile.json b/cli/samples/raft-common-file-share/raft.restler.compile.json new file mode 100644 index 0000000..c6fbf4e --- /dev/null +++ b/cli/samples/raft-common-file-share/raft.restler.compile.json @@ -0,0 +1,20 @@ +{ + "swaggerLocation": { + "Url": "https://{defaults.deploymentName}-raft-apiservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "rootFileShare" : "raft", + "tasks": [ + { + "toolName" : "RESTler", + "outputFolder" : "compile", + "isIdling": false, + + "toolConfiguration" : { + "task": "compile", + "compileConfiguration": { + "useRefreshableToken": true + } + } + } + ] +} diff --git a/cli/samples/raft-common-file-share/raft.restler.fuzz.json b/cli/samples/raft-common-file-share/raft.restler.fuzz.json new file mode 100644 index 0000000..4a135a7 --- /dev/null +++ b/cli/samples/raft-common-file-share/raft.restler.fuzz.json @@ -0,0 +1,62 @@ +{ + "swaggerLocation": { + "Url" : "https://{defaults.deploymentName}-raft-apiservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "duration": "00:10:00", + "host": "{defaults.deploymentName}-raft-apiservice.azurewebsites.net", + "rootFileShare" : "raft", + "readOnlyFileShareMounts" : [ + { + "FileShareName" : "raft", + "MountPath" : "/job-compile" + } + ], + "tasks": [ + { + "toolName" : "RESTler", + "outputFolder" : "fuzz-1", + "isIdling" : false, + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + "toolConfiguration" : { + "task": "Fuzz", + "runConfiguration": { + "inputFolderPath": "/job-compile/{compile.jobId}/compile" + } + } + }, + + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-fuzz-random-walk-2", + "isIdling" : false, + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + "toolConfiguration" : { + "task": "FuzzRandomWalk", + "runConfiguration": { + "inputFolderPath": "/job-compile/{compile.jobId}/compile" + } + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-fuzz-bfscheap-3", + "isIdling" : false, + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + "toolConfiguration" : { + "task": "FuzzBfsCheap", + "runConfiguration": { + "inputFolderPath": "/job-compile/{compile.jobId}/compile" + } + } + } + ] +} diff --git a/cli/samples/raft-common-file-share/raft.restler.replay.json b/cli/samples/raft-common-file-share/raft.restler.replay.json new file mode 100644 index 0000000..0ff7872 --- /dev/null +++ b/cli/samples/raft-common-file-share/raft.restler.replay.json @@ -0,0 +1,28 @@ +{ + "host": "{defaults.deploymentName}-raft-apiservice.azurewebsites.net", + "rootFileShare" : "raft", + "readOnlyFileShareMounts" : [ + { + "FileShareName" : "raft", + "MountPath" : "/job-run" + } + ], + "tasks": [ + { + "toolName" : "RESTler", + "outputFolder" : "RESTLer-replay", + "isIdling" : false, + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + + "toolConfiguration" : { + "task": "Replay", + "runConfiguration" :{ + "inputFolderPath": "/job-run/{jobRunId}/fuzz-1" + } + } + } + ] +} diff --git a/cli/samples/raft-common-file-share/raft.restler.test.json b/cli/samples/raft-common-file-share/raft.restler.test.json new file mode 100644 index 0000000..8659f5f --- /dev/null +++ b/cli/samples/raft-common-file-share/raft.restler.test.json @@ -0,0 +1,46 @@ +{ + "swaggerLocation": { + "Url" : "https://{defaults.deploymentName}-raft-apiservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "host": "{defaults.deploymentName}-raft-apiservice.azurewebsites.net", + "rootFileShare" : "raft", + "readOnlyFileShareMounts" : [ + { + "FileShareName" : "raft", + "MountPath" : "/job-compile" + } + ], + "tasks": [ + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-test", + "isIdling" : false, + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + "toolConfiguration" : { + "task": "Test", + "runConfiguration": { + "inputFolderPath": "/job-compile/{compile.jobId}/compile" + } + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-test-fuzz-lean", + "isIdling" : false, + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + "toolConfiguration" : { + "task": "TestFuzzLean", + "runConfiguration": { + "inputFolderPath": "/job-compile/{compile.jobId}/compile", + "authenticationTokenRefreshIntervalSeconds": 300 + } + } + } + ] +} diff --git a/cli/samples/raft-common-file-share/raft.zap.json b/cli/samples/raft-common-file-share/raft.zap.json new file mode 100644 index 0000000..4fc8e27 --- /dev/null +++ b/cli/samples/raft-common-file-share/raft.zap.json @@ -0,0 +1,18 @@ +{ + "swaggerLocation": { + "Url" : "https://{defaults.deploymentName}-raft-apiservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "host": "{defaults.deploymentName}-raft-apiservice.azurewebsites.net", + "rootFileshare" : "raft", + "tasks": [ + { + "isIdling" : false, + "toolName": "ZAP", + "outputFolder" : "zap-out", + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + } + } + ] +} \ No newline at end of file diff --git a/cli/samples/raft/raft-restler.py b/cli/samples/raft/raft-restler.py new file mode 100644 index 0000000..0d24709 --- /dev/null +++ b/cli/samples/raft/raft-restler.py @@ -0,0 +1,43 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import pathlib +import sys +import os +import json +import urllib.parse + +cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(cur_dir, '..', '..')) +from raft_sdk.raft_service import RaftCLI, RaftJobConfig + +def run(compile, test, fuzz): + cli = RaftCLI() + substitutions = { + '{defaults.deploymentName}': cli.definitions.deployment + } + compile_job_config = RaftJobConfig(file_path=compile, substitutions=substitutions) + print('Compile') + # create a new job with the Compile config and get new job ID + # in compile_job + compile_job = cli.new_job(compile_job_config) + # wait for a job with ID from compile_job to finish the run + cli.poll(compile_job['jobId']) + substitutions['{compile.jobId}'] = compile_job['jobId'] + + print('Test') + test_job_config = RaftJobConfig(file_path=test, substitutions=substitutions) + test_job = cli.new_job(test_job_config) + cli.poll(test_job['jobId']) + + print('Fuzz') + fuzz_job_config = RaftJobConfig(file_path=fuzz, substitutions=substitutions) + fuzz_job = cli.new_job(fuzz_job_config) + cli.poll(fuzz_job['jobId']) + + + +if __name__ == "__main__": + run(os.path.join(cur_dir, "raft.restler.compile.json"), + os.path.join(cur_dir, "raft.restler.test.json"), + os.path.join(cur_dir, "raft.restler.fuzz.json")) \ No newline at end of file diff --git a/cli/samples/raft/raft-zap.py b/cli/samples/raft/raft-zap.py new file mode 100644 index 0000000..cf1154f --- /dev/null +++ b/cli/samples/raft/raft-zap.py @@ -0,0 +1,23 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import pathlib +import sys +import os +import json +import urllib.parse + +cur_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(cur_dir, '..', '..')) +from raft_sdk.raft_service import RaftCLI, RaftJobConfig + +def run(run_zap): + cli = RaftCLI() + run_zap_config = RaftJobConfig(file_path=run_zap, + substitutions={'{defaults.deploymentName}' : cli.definitions.deployment}) + zap_job = cli.new_job(run_zap_config) + print(zap_job) + cli.poll(zap_job['jobId']) + +if __name__ == "__main__": + run(os.path.join(cur_dir, "raft.zap.json")) \ No newline at end of file diff --git a/cli/samples/raft/raft.restler.compile.json b/cli/samples/raft/raft.restler.compile.json new file mode 100644 index 0000000..77f737b --- /dev/null +++ b/cli/samples/raft/raft.restler.compile.json @@ -0,0 +1,29 @@ +{ + "swaggerLocation": { + "URL" : "https://{defaults.deploymentName}-raft-apiservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "tasks": [{ + "toolName": "RESTler", + "outputFolder" : "RESTler-compile", + "isIdling": false, + + "toolConfiguration": { + "task": "compile", + "compileConfiguration": { + "useRefreshableToken": true, + "customDictionary": { + "customPayload": { + "duration": ["00:10:00"], + "swaggerLocation": ["{\"URL\": \"https://some.service.azurewebsites.net/swagger.json\"}"], + "authenticationMethod": ["{\"CommandLine\": \"abc\" }"], + "targetUrl":["{replace-with-valid-webhook-URL}"], + "event": ["JobStatus"], + "timeSpanFilter": ["00:10:00"], + "eventName": ["JobStatus"] + } + } + } + } + } + ] +} diff --git a/cli/samples/raft/raft.restler.fuzz.json b/cli/samples/raft/raft.restler.fuzz.json new file mode 100644 index 0000000..a2ae4cd --- /dev/null +++ b/cli/samples/raft/raft.restler.fuzz.json @@ -0,0 +1,51 @@ +{ + "swaggerLocation": { + "URL" : "https://{defaults.deploymentName}-raft-apiservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "host": "{defaults.deploymentName}-raft-apiservice.azurewebsites.net", + "duration": "00:10:00", + "ReadOnlyFileShareMounts" : [ + { + "fileShareName" : "{compile.jobId}", + "mountPath" : "/job-compile" + } + ], + "tasks": [ + { + "toolName" : "RESTler", + "isIdling" : false, + "outputFolder" : "RESTler-random-walk-fuzz", + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + + "toolConfiguration" : { + "task": "FuzzRandomWalk", + "runConfiguration": { + "inputFolderPath": "/job-compile/RESTler-compile", + "useSsl": true, + "producerTimingDelay": 5 + } + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-fuzz", + "isIdling" : false, + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + + "toolConfiguration" : { + "task": "Fuzz", + "runConfiguration": { + "inputFolderPath": "/job-compile/RESTler-compile", + "useSsl": true, + "producerTimingDelay": 5 + } + } + } + ] +} diff --git a/cli/samples/raft/raft.restler.test.json b/cli/samples/raft/raft.restler.test.json new file mode 100644 index 0000000..dbf437d --- /dev/null +++ b/cli/samples/raft/raft.restler.test.json @@ -0,0 +1,44 @@ +{ + "swaggerLocation": { + "URL" : "https://{defaults.deploymentName}-raft-apiservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "host": "{defaults.deploymentName}-raft-apiservice.azurewebsites.net", + "ReadOnlyFileShareMounts" : [ + { + "fileShareName" : "{compile.jobId}", + "mountPath" : "/job-compile" + } + ], + "tasks": [ + { + "toolName" : "RESTler", + "outputFolder": "RESTLer-test-fuzz-lean-1", + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + + "toolConfiguration" : { + "task": "TestFuzzLean", + "runConfiguration": { + "inputFolderPath": "/job-compile/RESTler-compile", + "authenticationTokenRefreshIntervalSeconds": 300 + } + } + }, + { + "toolName" : "RESTler", + "outputFolder" : "RESTler-test-2", + "keyVaultSecrets" : ["RaftServicePrincipal"], + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + }, + "toolConfiguration" : { + "task": "Test", + "runConfiguration": { + "inputFolderPath": "/job-compile/RESTler-compile" + } + } + } + ] +} diff --git a/cli/samples/raft/raft.zap.json b/cli/samples/raft/raft.zap.json new file mode 100644 index 0000000..a57d58a --- /dev/null +++ b/cli/samples/raft/raft.zap.json @@ -0,0 +1,18 @@ +{ + "swaggerLocation": { + "URL" : "https://{defaults.deploymentName}-raft-apiservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "host": "{defaults.deploymentName}-raft-apiservice.azurewebsites.net", + "tasks": [ + { + "isIdling" : false, + "toolName": "ZAP", + "keyVaultSecrets" : ["RaftServicePrincipal"], + "outputFolder" : "zap-results", + + "authenticationMethod": { + "MSAL": "RaftServicePrincipal" + } + } + ] +} \ No newline at end of file diff --git a/docs/cli/job.md b/docs/cli/job.md new file mode 100644 index 0000000..35eb2b9 --- /dev/null +++ b/docs/cli/job.md @@ -0,0 +1,74 @@ +# Job Commands + +## job-create \ + +Creates a new job. The \ file defines the job and tasks to run. + +* **--duration** specifies how long the job should run. This is a TimeSpan value.
+ The duration can also be specified in the job definition. If it is defined in the job definition and this parameter is used, this value will be the one used. It overrides the job definition value. +* **--read-only-mounts** specifies which file shares will be mounted to the new job as a read-only file share.
+ This is helpful when multiple jobs need to access the same information.
+ +``` +Usage: --read-only-mounts '[{"FileShareName":"grade-track-compile-48297e1a-9cb4-4578-8fa1-15bd8949affb", "MountPath": "/job-compile"}]' +``` + +* **--read-write-mounts** specified file shares which will be mounted with read-write access. + +``` +Usage: --read-write-mounts '[{"FileShareName":"MyData", "MountPath": "/personalData "}]' +``` + +* **--poll \** takes a value which is used as the job status polling interval in seconds.
+ Polling terminates once the job has completed. +* **--metadata** Arbitrary key/value pairs can be passed to a job.
+ This data will be returned in webhooks. In this way you can track things like branch names, change authors, bug numbers, etc in your jobs. +If you have a logic app which handles your bugFound webhook by creating a bug in your bug tracking system, you could have this data available in the bug. + +``` +Usage: --metadata '{"BuildNumber":"pipelineBuildNumber", "Author": "John"}' +``` + +Returns a \ as json. + +``` +Example: {'jobId': '0a0fd91f-8592-4c9d-97dd-01c9c3c44159'} +``` + +The jobId that is returned is a string that will contain a guid, if you decide to use a namePrefix in the job definition, the guid will be prepended with the prefix. + +## job-status \
+ +Gets the status of a job. + +``` +Usage: job-status ffc4a296-f85d-4122-b49b-8074b88c9755 +``` + +## job-list --look-back-hours
+ +List the status of all jobs. By default the command will return the status of all jobs over the last 24 hours. +Use `--look-back-hours` to specify a different time frame. For example to look back over the last hour + +``` +Usage: job-list --look-back-hours 1 +``` + +## job-update \ \
+ +Deploy a job definition to an existing job. This is useful when the job is deployed with the "isIdling" flag set to true +which tells the service to not delete the container when the job has completed. In this way it is possible to quickly +deploy a new job without waiting for container creation. + +It is also possible to use `ssh` to log into the container if manual exploration of the container is needed. +If the container is not running for some reason, the job will be created as normal. +If the job container creation failed for some reason, the job will not be created. You can check the application insights log for failures. + +## job-delete \
+ +Deletes the job. By default jobs are garbage collected when they have completed their run. +However, if "isIdling" is set to true, manual job deletion is required. + +## job-results-url \
+ +Returns a url to the storage file share where the job results are stored. Use the url in your browser to go directly to the results. diff --git a/docs/cli/logout.md b/docs/cli/logout.md new file mode 100644 index 0000000..ec15fe8 --- /dev/null +++ b/docs/cli/logout.md @@ -0,0 +1,6 @@ +# Logout command + +## logout + +The logout parameter will remove the cashed tokens. +The next use of the CLI will require that you re-authenticate. \ No newline at end of file diff --git a/docs/cli/overview.md b/docs/cli/overview.md new file mode 100644 index 0000000..7846fd9 --- /dev/null +++ b/docs/cli/overview.md @@ -0,0 +1,25 @@ +# Using the RAFT command line + +The Raft command line interface is written in python and is simply an interface to the REST commands in the service. +Anything you can do with the CLI you can do with any tool that can interact with REST interfaces. +PostMan, curl, to mention a few. +The Raft CLI is both a command line interface which parses commands and executes them, +and an SDK which you can import and script the underlying functions yourself. + +## CLI Commands + +In our CLI syntax, values without two dashes "--" are positional parameters. +When they are separated by "|" as in [ red | blue | yellow ] select one value. +Parameters with two dashes "--" are always optional + +### General Parameters + +These parameters apply to all commands. + + + +**--secret \**
+When **--skip-sp-deployment** is used, new secret generation is not executed. +However, the deployment will overwrite configuration settings for the APIService and the Orchestrator. +These services need to know the service principal secret. +Use this parameter to pass the secret to the deployment process. \ No newline at end of file diff --git a/docs/cli/service.md b/docs/cli/service.md new file mode 100644 index 0000000..35d4974 --- /dev/null +++ b/docs/cli/service.md @@ -0,0 +1,23 @@ +# Service Commands: + +## service [deploy | restart | info] + +The **deploy** parameter has the following options + +**--sku option**
+ +* The allowed sku values are: 'B1', 'B2', 'B3', 'D1', 'F1', 'FREE','I1', 'I2', 'I3', 'P1V2','P2V2','P3V2','PC2', 'PC3', 'PC4', 'S1', 'S2', 'S3', 'SHARED' +* These correspond to the App Service Plan sizes. The default is B2. Note that is a linux app service plan. + +**--skip-sp-deployment**
+* When using the Azure DevOps pipeline to re-deploy the service during code development, +this parameter can be used to skip the service principal deployment. +The assumption here is that the service principal has already been deployed. +In this scenario, use of the --secret parameter is required. + +The **restart** parameter will restart the api service and the orchestrator.
+When the services restart if there is a new version of the software it will be downloaded. + +The **info** parameter will return version information about the service and the last time it was restarted.
+Example: `{'version': '1.0.0.0', 'serviceStartTime': '2020-08-04T21:05:53+00:00'}` + diff --git a/docs/cli/webhook.md b/docs/cli/webhook.md new file mode 100644 index 0000000..4fb8363 --- /dev/null +++ b/docs/cli/webhook.md @@ -0,0 +1,29 @@ +# Webhook Commands
+ +These commands are used to create and control webhooks. Webhooks are implemented by using an [EventDomain](https://docs.microsoft.com/en-us/azure/event-grid/event-domains) + +## webhook-events
+ +Lists the set of events which will generate webhooks. + +## webhook-create \ --event \ --url \
+ +Creates a webhook. The \ value is a string that is used in your jobDefinition file. +The --event \ parameter is required. The event name must be one of the values returned from webhook-events. +The --url \ parameter is required. The targetUrl will receive the webhook. The targetUrl must implement endpoint validation. See https://docs.microsoft.com/en-us/azure/event-grid/webhook-event-delivery +A common and simple use as the target is an azure logic app. This provides a simple way to process your webhooks posting to teams or slack, creating new work items, etc. + +## webhook-test \ --event \
+ +Test your webhook receiver. Dummy data will be sent to the webhook endpoint you are testing. +The **--event** parameter is required. + +## webhook-list \
+ +List the definition of webhook \. +Use of **--event** parameter is optional to limit what is returned. + +## webhook-delete \ --event \
+ +Deletes a webhook for a specific event. +The **--event** parameter is required. \ No newline at end of file diff --git a/docs/deploying/deploying.md b/docs/deploying/deploying.md new file mode 100644 index 0000000..f4ddb98 --- /dev/null +++ b/docs/deploying/deploying.md @@ -0,0 +1,63 @@ +# Installing RAFT + +* Get the RAFT CLI from [releases.](https://github.com/microsoft/raft/releases) + +**Prerequisites:** + +* An azure subscription
+ It is helpful if you are the **owner** on the azure subscription that you are deploying to. + + During deployment, the script will create a service principle, +this service principle needs to be given access to the newly created resource group. +You must have owner permissions for the script to do the assignment. + + If you are not the subscription owner you will need to have the owner manually assign the service principle to the resource group that is created. +The service principle should be given `contributor` access to the resource group that was created. + +## Container Instances + +RAFT uses container instances and by default subscriptions are limited to 100 instances, +if you are an existing user of container instances on the selected subscription, +you may need to reach out to Azure support to ask for an increase of Linux container instances. + +## Installation Process + +* Run the command `python .\raft.py service deploy`
+ The first time you run this command you will be asked to fill in some values in a `defaults.json` file. This file is used to describe the context for the cli. + +``` +subscription - The Azure Subscription ID to which RAFT is deployed + +deploymentName - RAFT deployment name + deployment name requirements: + - only letters or numbers + - at most 24 characters long + - no capital letters + - no dashes + +region - Region to deploy RAFT (e.g. westus2) + See https://azure.microsoft.com/en-us/global-infrastructure/regions/ + for a list of regions + +metricsOptIn - allow Microsoft collect anonymized metrics from the deployment. + +useAppInsights - deploy AppInsights and use it to write all service logs + +registry - registry which stores service images. + +------------------------- +To apply any changes made to the defaults.json file, +please run 'raft.py service deploy' +------------------------- + +``` + +The only values you **MUST** change are: + +* subscription - this is the azure subscription you own where you will be installing the service +* deploymentName - this is used to name a resource group and services with "-raft" appended +* region - the region to use for the services. We recommend a region that is close to your location. Find the list of available regions [here](https://azure.microsoft.com/en-us/global-infrastructure/geographies/). +* metricsOptIn - by default we collect anonymous metrics to help us improve the service. + To opt-out simply set this value to false. If you change your mind at some point, update this value and re-deploy the service. + +Once the default.json file has been updated, re-run `python .\raft.py service deploy`. Most deployments complete in about 15 minutes. diff --git a/docs/deploying/onboarding-your-tools.md b/docs/deploying/onboarding-your-tools.md new file mode 100644 index 0000000..ac6e975 --- /dev/null +++ b/docs/deploying/onboarding-your-tools.md @@ -0,0 +1,120 @@ +# On-boarding your own tools +RAFT allows you to on-board any tool that is packaged into a docker container. +This means that any public (or private tool you develop) is available +to include in the test suite you design to test your services. + +**At this time only Linux containers are supported.** + +## Tool Configuration + +Tools are packaged in containers. These containers are then deployed into a [container instance](https://azure.microsoft.com/en-us/services/container-instances/). +[See subscription default quota's and limits](https://docs.microsoft.com/en-us/azure/container-instances/container-instances-quotas#service-quotas-and-limits) +to understand your scaling limits. + +See [Container Instance Pricing](https://azure.microsoft.com/en-us/pricing/details/container-instances/) to understand the cost +implications of running your tool. + +### 1. Create the folder +Your first step in integrating a tool is to create a folder under cli/raft-utils/tools. +Give your tool a name, this is the name that you will use in the jobDefinition "toolName" field. +The name is case sensitive. + +Let's assume we have a tool called demoTool. Create the folder.
+![](../images/demotool-folder.jpg) + +### 2. Create config.json + +The config.json file defines the commands that will run your tool. It also defines +the resources needed by the container. + +``` +{ + "container" : "demoTool/demoTool-stable", + + "run" : { + "command" : "bash", + "arguments" : ["-c", + "cd $RAFT_RUN_DIRECTORY; ln -s $RAFT_WORK_DIRECTORY /demoTool; python3 run.py install; python3 run.py" ] + }, + "idle" : { + "command" : "bash", + "arguments" : ["-c", "echo DebugMode; while true; do sleep 100000; done;"] + } +} +``` + +In this example, the "container" field defines the docker image. By default dockerhub is +searched for the image. + +#### Private Registries +If you want to specify an image from a private repository, create a secret that starts with the +string `PrivateRegistry` in the key vault. +This secret will be a json blob consisting of repository name, user name, and password. +For example: + +``` + { + "repository" : "myprivateRegistry.azurecr.io", + "user" : "myUsername", + "password" : "myPassword" + } +``` + +When the orchestrator starts, it will search the key vault for secrets that begin with `PrivateRegistry` and register +each one so it is available for use. + +These key vault entries will be registered in alphabetical order of the secrets. +Registries will be searched for the requested image in the same order, starting with the public docker registry, and +then moving though the private registries. + +#### Container resources +The "containerConfig" section defines the set of resources that will be allocated to the container. +"CPUs", "MemorySizeInGB", and "GPUs" can be defined. + +#### Commands + +The `run` and `idle` commands are used in two different job launch scenarios. `run` is used to actually run +a job, and `idle` is used when you want to interactively work with the container. + +The "command" needs to be a command that is available on the container. In the "arguments" you can reference +environment variables that have been preset for you. + +The environment variables are: +* RAFT_JOB_ID
+ This is the id of the currently executing job. If you generate events, this will be needed. +* RAFT_CONTAINER_GROUP_NAME +* RAFT_CONTAINER_NAME +* RAFT_APP_INSIGHTS_KEY
+ Use the app insights key if you want to log to the app insights instance created with the service. +* RAFT_WORK_DIRECTORY
+ In the work directory you will find a `task-config.json` that contains any data defined in the +job definition `toolConfiguration` section of the task. The format of this data is under your control. +For example, a RESTler job definition might contain the following toolConfiguration + + ``` + "toolConfiguration" : { + "task": "TestFuzzLean", + "agentConfiguration": { + "resultsAnalyzerReportTimeSpanInterval": "00:01:00" + }, + "runConfiguration": { + "previousStepOutputFolderPath": "/job-compile/0", + "useSsl": true, + "producerTimingDelay": 5 + } + } + ``` + This data fragment would be available in the task-config.json file. + +* RAFT_RUN_DIRECTORY
+ When the tool is uploaded to the file share via the cli command `python raft.py service upload-utils` +a unique file share is created and mounted to the container as read-only. This gives you an easy way to reference any scripts +or executables you launch. +* RAFT_RUN_CMD
+ The command that was run when the container was launched. + +### 3. Swagger schema for your tool (optional) + +If you specify a swagger document called schema.json in your tool folder, it will be folded in under the toolConfiguration +node in the service swagger. All component types referenced in the swagger must be defined in the file. +See the RESTler tool schema.json file as an example. \ No newline at end of file diff --git a/docs/deploying/telemetry.md b/docs/deploying/telemetry.md new file mode 100644 index 0000000..c35e6ad --- /dev/null +++ b/docs/deploying/telemetry.md @@ -0,0 +1,11 @@ +# Telemetry + +We collect anonymous telemetry metrics to help us improve the service. You can find all the data types that are collected in the +`telemetry.fs` file. + +## Opting out + +To opt-out the easiest way is to run the deployment with the metricsOptIn field in the defaults.json file set to false. + +You can also manually opt out by clearing the value from the setting `RAFT_METRICS_APP_INSIGHTS_KEY` in the apiservice and the orchestrator function app. +Do not delete the setting, simply clear the value. \ No newline at end of file diff --git a/docs/deploying/tools.md b/docs/deploying/tools.md new file mode 100644 index 0000000..1bb47ed --- /dev/null +++ b/docs/deploying/tools.md @@ -0,0 +1,8 @@ +# Tools deployed by default + +Two tools are deployed by default. [RESTler](https://github.com/microsoft/restler) and [ZAP](https://www.zaproxy.org/). + +You can see their configuration under the `cli/raft-utils/tools` folder. + +See an explanation of the `config.json` file in [How a job executes](../how-it-works/how-a-job-executes.md). + diff --git a/docs/deploying/validating.md b/docs/deploying/validating.md new file mode 100644 index 0000000..c58177b --- /dev/null +++ b/docs/deploying/validating.md @@ -0,0 +1,12 @@ +# Validating your installation + +Once your deployment has completed, you can check to see if the service is running by +executing the CLI command: + +`python raft.py service info` + +This will return information about the service including the version of the service installed and the date and time the service was last started. + +There are a number of samples in the sample folder. These are setup so that you can run +the python scripts directly to exercise the service. Take some time to look at the log files and +get familiar with the output. \ No newline at end of file diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 0000000..9da43f6 --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,15 @@ +# FAQ + +**I see 404's for GET /robots933456.txt in my Application Insights log** +
We deploy containers to the webapp. See this [explanation](https://docs.microsoft.com/en-us/azure/app-service/containers/configure-custom-container#robots933456-in-logs). + +**Why use file shares?** +
File shares can be mounted to the containers running tools. This provides an easy way to share data. + +The use of file shares makes it easy to upload your custom swagger files, and authentication configurations files. +You can also view real time log changes and results in the files share during the job run, +and mount these file shares to your computer for a better user experience. + +To mount the file share, use the connect button on the azure portal. + +![Connect File Share Image](images/mount_file_share.jpg) diff --git a/docs/how-it-works/azure-resources.md b/docs/how-it-works/azure-resources.md new file mode 100644 index 0000000..2493173 --- /dev/null +++ b/docs/how-it-works/azure-resources.md @@ -0,0 +1,14 @@ +# Azure Resources +Raft is a service that is built on [Azure](https://azure.microsoft.com/en-us/). All you need to get started is an Azure [subscription](https://azure.microsoft.com/en-us/free/). + +The deployment script will create all the resources that you need for the service. Use the [Azure portal](https://portal.azure.com) to view the created resources. + +The resources that are used by the service are: +* Application Insights (for logging) +* App Service (for the front-end API) +* App Service Plan (VM's used for App Service and Azure functions) +* Event Grid Domain (for webhooks) +* Key vault (for secret management) +* Funtion app (for service orchestration) +* Service Bus (for messaging between components of the service) +* Storage accounts (one for the service use and one for all your data) \ No newline at end of file diff --git a/docs/how-it-works/how-a-job-executes.md b/docs/how-it-works/how-a-job-executes.md new file mode 100644 index 0000000..63cd9d0 --- /dev/null +++ b/docs/how-it-works/how-a-job-executes.md @@ -0,0 +1,74 @@ +# How a job executes + +Jobs are submitted to the front-end service via a job definition written in json. Every job has one or more tasks. The `taskConfiguration` +portion of the job definition is information that is specific to the task that will run. + +This data is passed to the task by being written into a file called `task-config.json` and placed into the file share that +is the working directory for the task. The task can then deserialize and validate the data as needed. + +Under the CLI that is downloaded, you will find under the raft-utils/tools folder a folder for each installed tool. By default there are +tools for RESTler and ZAP. In the tool directory you will find a file called `config.json`. This file contains the configuration +data for how to run the tool. + +Here is the example for the ZAP tool. + +``` +{ + "container" : "owasp/zap2docker-stable", + "containerConfig" : { + "CPUs" : 2, + "MemorySizeInGB" : 1.0 + }, + + "run" : { + "command" : "bash", + "arguments" : ["-c", + "cd $RAFT_RUN_DIRECTORY; ln -s $RAFT_WORK_DIRECTORY /zap/wrk; python3 run.py install; python3 run.py" ] + }, + "idle" : { + "command" : "bash", + "arguments" : ["-c", "echo DebugMode; while true; do sleep 100000; done;"] + } +} +``` + +The "container" specifies the name of the docker container. The "containerConfig" allows you to specify the amount of compute resources you need for your tool. +The "run" structure allows you to specify the command to run and it's arguments on the container. The "idle" structure is what is run when +the tool is marked as "isDebug". + +The available commands and arguments are limited by what is available in the container you select. + +The schema for the tool configuration is + +``` + type ToolCommand = + { + command : string + arguments: string array + } + + + type ToolConfig = + { + container : string + containerConfig : ContainerConfig option + run : ToolCommand + idle : ToolCommand + } +``` + +## Environment Variables +A number of pre-defined environment variables are available in the container for your use. + +* RAFT_JOB_ID +* RAFT_TASK_INDEX +* RAFT_CONTAINER_GROUP_NAME +* RAFT_CONTAINER_NAME +* RAFT_APP_INSIGHTS_KEY +* RAFT_WORK_DIRECTORY +* RAFT_RUN_DIRECTORY +* RAFT_SB_OUT_SAS
+ This can be used to write event our to the service bus so your tool can generate job status and webhook data. + +Paths specified in the environment variables are Linux specific paths. + diff --git a/docs/how-it-works/job-output.md b/docs/how-it-works/job-output.md new file mode 100644 index 0000000..1ecfa4c --- /dev/null +++ b/docs/how-it-works/job-output.md @@ -0,0 +1,7 @@ +# Job Output + +Every tool has it's own way of generating output. Within the container, the working directory is a mounted file share. +The tool can create folders, write output, in whatever forms are desired. + +You have the ability to launch commands that connect to these output sources and generate job status or webhook data. See the +ZAP `scan.py` script as an example. diff --git a/docs/how-it-works/overview.md b/docs/how-it-works/overview.md new file mode 100644 index 0000000..a7a1a4f --- /dev/null +++ b/docs/how-it-works/overview.md @@ -0,0 +1,11 @@ +# Overview + +Job configurations are submitted to the RAFT service front-end. +A message is put onto the service bus and processed by the back-end orchestrator. +Once the message is received an Azure storage File Share is created with the job Id as the share name. +The orchestrator creates a container group for each job. The container group name is the job Id and you can see it in the portal in the resource group where the service was deployed. +Each task runs as a container within the container group. + +The file share is mounted to each container in the container group as the "working directory" where the running tool should write all its results. +When an agent processes the task output, it may send job progress events on the service bus. These events are recorded in the job status azure table by job id. +Status can be retrieved with the CLI or with a REST API call to the RAFT service. \ No newline at end of file diff --git a/docs/images/connect.png b/docs/images/connect.png new file mode 100644 index 0000000..cb06613 Binary files /dev/null and b/docs/images/connect.png differ diff --git a/docs/images/containerInstanceInPortal.jpg b/docs/images/containerInstanceInPortal.jpg new file mode 100644 index 0000000..6f1c284 Binary files /dev/null and b/docs/images/containerInstanceInPortal.jpg differ diff --git a/docs/images/containersTab.jpg b/docs/images/containersTab.jpg new file mode 100644 index 0000000..45e9f87 Binary files /dev/null and b/docs/images/containersTab.jpg differ diff --git a/docs/images/demotool-folder.jpg b/docs/images/demotool-folder.jpg new file mode 100644 index 0000000..60b883a Binary files /dev/null and b/docs/images/demotool-folder.jpg differ diff --git a/docs/images/mount_file_share.jpg b/docs/images/mount_file_share.jpg new file mode 100644 index 0000000..915e5bf Binary files /dev/null and b/docs/images/mount_file_share.jpg differ diff --git a/docs/images/postman-auth.png b/docs/images/postman-auth.png new file mode 100644 index 0000000..2f143ac Binary files /dev/null and b/docs/images/postman-auth.png differ diff --git a/docs/images/postman-inherit-auth.jpg b/docs/images/postman-inherit-auth.jpg new file mode 100644 index 0000000..afd96ac Binary files /dev/null and b/docs/images/postman-inherit-auth.jpg differ diff --git a/docs/images/postman-request-token.jpg b/docs/images/postman-request-token.jpg new file mode 100644 index 0000000..fe9dab3 Binary files /dev/null and b/docs/images/postman-request-token.jpg differ diff --git a/docs/images/terminalExample.jpg b/docs/images/terminalExample.jpg new file mode 100644 index 0000000..f0a1eae Binary files /dev/null and b/docs/images/terminalExample.jpg differ diff --git a/docs/images/webhook_demo.jpg b/docs/images/webhook_demo.jpg new file mode 100644 index 0000000..dbf74cc Binary files /dev/null and b/docs/images/webhook_demo.jpg differ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..35763c9 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,34 @@ +# Table of Contents + +* [FAQ](faq.md) +* How it works + * [Overview](how-it-works/overview.md) + * [Azure resources](how-it-works/azure-resources.md) + * [How a job executes](how-it-works/how-a-job-executes.md) + * [Job output](how-it-works/job-output.md) +* Deploying RAFT + * [Telemetry opt-out](deploying/telemetry) + * [Deploying RAFT](deploying/deploying.md) + * [Tools deployed by default](deploying/tools.md) + * [Validating the install](deploying/validating.md) + * [On-boarding your own tools](deploying/onboarding-your-tools.md) +* Using the RAFT command line + * [Overview](cli/overview.md) + * [Service commands](cli/service.md) + * [Job commands](cli/job.md) + * [Webhook commands](cli/webhook.md) + * [Logout](cli/logout.md) +* REST API + * [Swagger](sdk/swagger.md) + * [Authentication](schema/authentication) + * [Using Postman](schema/postman.md) +* Webhooks + * [Overview](webhooks/overview.md) + * [Creating](webhooks/creating.md) + * [Deleting](webhooks/deleting.md) + * [Testing](webhooks/testing.md) +* [Job Definition file](schema/jobdefinition.md) +* Troubleshooting + * [How to SSH to a container](troubleshooting/idle.md) +* SDK +* Samples diff --git a/docs/schema/authentication.md b/docs/schema/authentication.md new file mode 100644 index 0000000..2ee3d31 --- /dev/null +++ b/docs/schema/authentication.md @@ -0,0 +1,79 @@ +# Authentication + +When defining tasks, you can define the authentication needed by the task. + +The authentication data is described in the json and lives in the key vault. + +Here is an example of using MSAL for authentication. + +``` "tasks": [ + { + "toolName" : "RESTler", + "isIdling" : false, + "keyVaultSecrets" : ["AuthSecret1", "AuthSecret2"], + "authTokenConfiguration": { + "refreshIntervalSeconds": 300, + "tokenRefreshCommand": { + "$type" : "MSALConfig", + "secretName" : "AuthSecret1" + } + }, +``` + +In this example the secret "AuthSecret1" must contain the data needed for MSAL. + +When the container is created each secret defined in the "keyVaultSecrets" array are retrieved and added as +environment variables with the name "RAFT_" prepended. So for AuthSecret1 and AuthSecret2 you would find environment variables +"RAFT_AuthSecret1" and "RAFT_AuthSecret2" defined with the contents of their secrets from the key vault. + +These secret values can then be used to perform authentication as needed. + +Because environment variables cannot be named with a dash "-', you must not use a dash in your secret name. + +Some services need authentication refreshed at certain intervals. Use the **refreshIntervalSeconds** to define the +refresh frequency. + +The following authentication types are supported in the `$type` field. +## MSALConfig + +MSAL configuration stored in the key vault should be json in this form: + +``` +{ + "client": "", + "tenant": "", + "secret": "" + "scopes": ["example/.default"] +} +``` + +The "scopes" value is optional. Use this if you require a specific scope for your service. + +## TxtToken + +If your authentication takes a static token string use TxtToken. In this case the secret in the +key vault should simply be the token string. + +## CommandLine + +The command line type allows you to define your own command to create authentication data. + +You must provide all dependencies for your command. Put dependencies on a mounted file share as needed. + +## Other options + +For tools that support other authentication methods, the tool can define what is needed in the +taskConfiguration schema. This schema is completely tool dependent. + +For example in the RESTler configuration you might want to provide a static value in +a header value. + +``` +"compileConfiguration": { + "customDictionary": { + "customPayloadHeader": { + "": [""] + } + } + } +``` \ No newline at end of file diff --git a/docs/schema/jobdefinition.md b/docs/schema/jobdefinition.md new file mode 100644 index 0000000..67a063b --- /dev/null +++ b/docs/schema/jobdefinition.md @@ -0,0 +1,221 @@ +# Job Definition file + +Jobs are defined by a definition json. You can view the schema by looking at our +swagger UI. After the service is deployed, point your browser to the APIService to see +the swagger UI. + +For example if you deployment is named "myDeployment' point your browser to +`https://mydeployment-raft-apiservice/swagger` +This will display a web page with our REST methods and their schema's. + +The schema is defined in the code file DTOs.fs. + +Most fields in the job definition are optional, only a few are required. + +Here is an example job definition to fuzz a service with RESTler. +``` +{ + "swagger": { + "$type": "URL", + "value" : "https://my-appservice.azurewebsites.net/swagger/v1/swagger.json" + }, + "duration": "00:10:00", + "host": "my-appservice.azurewebsites.net", + "rootFileshare" : "myshare-fuzz", + "webhook" : "myservice-fuzz", + "tasks": [ + { + "toolName" : "RESTler", + "nameSuffix" : "-RESTler-fuzz", + "taskConfiguration" : { + "task": "Fuzz", + "agentConfiguration": { + "resultsAnalyzerReportTimeSpanInterval": "00:01:00" + }, + + "runConfiguration": { + "previousStepOutputFolderPath": "/job-compile/0-RESTler-Compile", + "useSsl": true, + "producerTimingDelay": 5 + } + } + }, + { + "toolName" : "RESTler", + "taskConfiguration" : { + "task": "Fuzz", + "agentConfiguration": { + "resultsAnalyzerReportTimeSpanInterval": "00:01:00" + }, + + "runConfiguration": { + "previousStepOutputFolderPath": "/job-compile/0-RESTler-Compile", + "useSsl": true, + "producerTimingDelay": 2 + } + } + } + ] +} +``` + +## Swagger (required object) + +Defines where to find the swagger file. This can be a Uri, or a file path which must reference +a file that is mounted on the container. + +``` + "swagger": { + "$type" : "URL", + "value": "https://someurl/swagger.json" + } +``` + +or + +``` +"swagger": { + "$type" : "FilePath", + "value": "/folderA/folderB/swagger.json" + } +``` + +## Tasks (required object) + +The task definition defines the tool that will run. This is an array of definitions. Up to 60 task +definitions can be defined in a single job. + +### ToolName (required string) + +Name of the tool. The two tools that are supported by default are `RESTler` and `ZAP` + +### Swagger (optional object) + +This swagger definition is the same definition as at the job level. This gives you the option +of specifying an alternate swagger file for this tool. + +### Host (optional string) + +Overwrite the host in every request by ZAP or RESTler instead of using the host value +in the swagger specification. + +### IsIdling (optional bool) + +If this boolean value is set, the container will be started using the "idle" command in the +tool configuration file. See the configuration files for tools under the raft_utils/tools folder. + +This setting is often used for interactively debugging the tool or examining what is on the container. +Access to the container is available through the Azure [Portal](https://portal.azure.com). + +The container will be created in the resource group which contains the resources for the service. +After clicking on the container you will see where you can connect to it interactively right in +the browser. + +### Duration (optional TimeSpan) + +Specify the duration for the task to run. + +### AuthTokenConfiguration (optional object) + +This object is used to define the kind of secret you are using, where it is located, and any +refresh interval if needed. + +See details on [authentication](authentication.md) + + +### KeyVaultSecrets (optional string) + +Key vault secrets must start with an alphabetic character and be followed by +a string a alphanumeric characters. Secret names can be up to 127 characters long. + +The key vault is used to hold your authentication secrets. Add your secret to the key vault using +any name for the secret you like. + +Your secret should be in the form expected for the type of secret you specify in the +authTokenConfiguration object. + + +## NamePrefix (optional string) + +The “namePrefix” is prepended to the job id guid. +This makes finding results in storage easily searchable by the prefix. +By combining the prefix with the timestamp it becomes easy to find job results. + +Some characters are **not allowed** in the namePrefix, these are forward slash (/), +backslash (\), number sign (#), question mark (?), control characters from U+000 +to U+001F including tab (\t), linefeed (\n), and carriage return (\r), +and control character from U+007F to U+009F. + +`"namePrefix" : "someUniquePrefix"` + +## Host (optional string) + +Overrides the host value defined in the swagger file. + +`"host": "myservice.azurewebsites.net"` + +## Webhook (optional string) + +The tag used to send webhooks. + +`"webhook" : "myhook"` + +## Metadata (optional string) + +Key/value pairs to include in webhook messages. This can be helpful when wanting to trace +who did a particular fix, or which branch is actually under test. These can be values from your +CI/CD pipeline. + +`"metadata": {"key" : "value", "author" : "john", "branch" : "mybranch"}` + +## Duration (optional string) + +This is a timespan value that defines how long a job should run. +If undefined it will run until completion (or forever if the task never completes). +For RESTler jobs, the the limit is only useful for Fuzz tasks. +The timespan format is defined [here](https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-timespan-format-strings). + +This example shows days.hours:minutes:seconds + +`"duration": "0.00:10:00"` + +## ReadOnlyFileShareMounts (optional string) + +Used to mount a file share read-only within the container. +The system will mount a file share from the storage account into the container for +tools to access. You can specify the name of the share to mount and the name it should be +mounted as within the container. In this example the file share name in the storage +account is “service-biz-swagger”. + +File share names have certain restrictions. See [here](https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-shares--directories--files--and-metadata). +The mount path is the name under which it will be available within the container. + +``` +"readOnlyFileShareMounts": [{ + "FileShareName": "service-biz-swagger", + "MountPath": "/swagger" + } + ] +``` + +## ReadWriteFileShareMounts (optional string) + +Used in the same way as the readOnlyFileShareMounts, but within the container +it’s mounted as a read-write share. + +```"readWriteFileShareMounts": [{ + "FileShareName": "service-biz-swagger", + "MountPath": "/swagger" + } + ] +``` + +## RootFileShare (optional string) + +When specified the results will be organized by jobId under this file share. +This is an easy way to collect similar runs together. Also since file shares can be +mounted onto your local dev machine, it is easy to browse all the log files or to +use utilities to parse the log files. +Name requirements are specified [here](https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-shares--directories--files--and-metadata#share-names) + +`"rootFileshare" : "mysharename"` \ No newline at end of file diff --git a/docs/schema/postman.md b/docs/schema/postman.md new file mode 100644 index 0000000..317a16a --- /dev/null +++ b/docs/schema/postman.md @@ -0,0 +1,90 @@ +# Using postman with the API + +Using postman to send requests to the API is straight forward. Create a collection, establish the scripts for authentication, and send requests. + +## Authentication + +The APIService webapp expects a bearer token on each api request. + +Postman can handle the creation of bearer tokens. See https://learning.postman.com/docs/postman/sending-api-requests/authorization/ for more details. + +### Edit App Registration in Azure Portal +In order to enable creation and use of the bearer token in postman you will need to update the app registration in Azure AD to add a URI callback. + +Using the azure portal, edit your app registration. + Add the value `https://www.getpostman.com/oauth2/callback` as a Redirect URI. + + +### Manual Token Generation in Postman + +* Use the Auth tab on the request (or on the collection). +* Select `OAuth 2.0` and click on the `Get New Access Token` button.
+![](../images/postman-auth.png) + +* Add the Callback URL `https://www.getpostman.com/oauth2/callback` +* The `Auth URL` should be `https://login.microsoftonline.com/microsoft.onmicrosoft.com/oauth2/authorize?resource=00000000-1234-1234-0000-000000000000` +The guid assigned to the resource is the client id of the app registration +* Enter the Client ID in the Client ID field. +![](../images/postman-request-token.jpg +) + +## Auto Token Generation +It is possible to have Postman created the token automatically as needed before sending the request. +The idea is that you have the pre-request script run and generate the token. The script sets the token to +an environment variable which then is used by the request. + +Edit your collection of requests and set the 'Pre-request Scripts' to +``` +const echoPostRequest = { + url: 'https://login.microsoftonline.com//oauth2/token', + method: 'POST', + header: 'Content-Type:application/x-www-form-urlencoded', + body: { + mode: 'urlencoded', + urlencoded: [ + { key: "client_id", value: "your client id here" }, + { key: "client_secret", value: "your secret here" }, + { key: "resource", value: "your client id here" }, + { key: "grant_type", value: "client_credentials" }, + ] + } +}; + +var getToken = true; + +if (!pm.environment.get('accessTokenExpiry') || + !pm.environment.get('currentAccessToken')) { + console.log('Token or expiry date are missing') +} else if (pm.environment.get('accessTokenExpiry') <= (new Date()).getTime()) { + console.log('Token is expired') +} else { + getToken = false; + console.log('Token and expiry date are all good'); +} + +if (getToken === true) { + console.log('getToken is true') + pm.sendRequest(echoPostRequest, function (err, res) { + console.log(err ? err : res.json()); + if (err === null) { + console.log('Saving the token and expiry date') + var responseJson = res.json(); + pm.environment.set('currentAccessToken', responseJson.access_token) + + var expiryDate = new Date(); + expiryDate.setSeconds(expiryDate.getSeconds() + responseJson.expires_in); + pm.environment.set('accessTokenExpiry', expiryDate.getTime()); + } else { + console.log('Error') + } + }); +} +``` + +* Add two environment variables. accessTokenExpiry and currentAccessToken. +* Under the Authorization tab, select the authorization type `Bearer Token` and set the token to `{{currentAccessToken}}` +* For every request in your collection, set the Auth value to `Inherit auth from parent` + +![](../images/postman-inherit-auth.jpg) + +Now this script will run and get a token before every request as needed. \ No newline at end of file diff --git a/docs/sdk/swagger.md b/docs/sdk/swagger.md new file mode 100644 index 0000000..8307464 --- /dev/null +++ b/docs/sdk/swagger.md @@ -0,0 +1,812 @@ +# Swagger + +The RAFT REST API is represented in a UI that can be viewed at your https://\/swagger. +This UI also will display the schema's for the various supported methods. + +Listed below is a static view of the swagger methods. + + + +

Access

+ +

Methods

+[ Jump to Models ] + +

Table of Contents

+
+

Info

+ +

Jobs

+ +

Webhooks

+ + +

Info

+
+
+ +
get /info
+
Returns information about the system.
+
This is an unauthenticated method. +Sample response: +{ +"version": "1.0.0.0", +"serviceStartTime": "2020-07-02T15:28:57.0093727+00:00" +}
+ + + + + + + + + + + + +

Responses

+

200

+Returns success. + +
+
+
+
+ +
get /
+
Test to see if service is up
+
This is an unauthenticated method which returns no data.
+ + + + + + + + + + + + +

Responses

+

200

+ Returns success if the service is running. + +
+
+

Jobs

+
+
+ +
get /jobs/v1
+
Returns in an array status for all jobs over the last 24 hours.
+
The default timespan is over the last 24 hours. Use the query string timeSpanFilter="TimeSpan" to specify a different interval. +Use a time format that can be parsed as a TimeSpan data type. +If no data is found the result will be an empty array.
+ + + + + +

Query parameters

+
+
timeSpanFilter (optional)
+ +
Query Parameter — A string which is interpreted as a TimeSpan format: date-span
+ + + + + + + +

Responses

+

200

+ Returns the job status data + +
+
+
+
+ +
delete /jobs/v1/{jobId}
+
Deletes a job
+
+ +

Path parameters

+
+
jobId (required)
+ +
Path Parameter — The id which refers to an existing job
+ + + + + + + + + + +

Produces

+ This API call produces the following media types according to the Accept request header; + the media type will be conveyed by the Content-Type response header. +
    +
  • application/json
  • +
+ +

Responses

+

200

+ Returns the newly created jobId + +

404

+ If the job was not found + inline_response_400 +
+
+
+
+ +
get /jobs/v1/{jobId}
+
Returns status for the specified job.
+
+ +

Path parameters

+
+
jobId (required)
+ +
Path Parameter
+ + + + + + + + + + + +

Responses

+

200

+ Returns the job status data + +

404

+ If the job was not found + +
+
+
+
+ +
post /jobs/v1/{jobId}
+
Repost a job definition to an existing job.
+
The existing job must have been created with isIdling set to true.
+ +

Path parameters

+
+
jobId (required)
+ +
Path Parameter — The id which refers to an existing job
+ +

Consumes

+ This API call consumes the following media types via the Content-Type request header: +
    +
  • application/json-patch+json
  • +
  • application/json
  • +
  • text/json
  • +
  • application/*+json
  • +
+ +

Request body

+
+
body JobDefinition (optional)
+ +
Body Parameter — The new job definition to run
+
+ + + + + + + + +

Produces

+ This API call produces the following media types according to the Accept request header; + the media type will be conveyed by the Content-Type response header. +
    +
  • application/json
  • +
+ +

Responses

+

200

+ Returns the newly created jobId + +

400

+ If there was an error in the request + inline_response_400 +
+
+
+
+ +
post /jobs/v1
+
Submit a job definition.
+
+ + +

Consumes

+ This API call consumes the following media types via the Content-Type request header: +
    +
  • application/json-patch+json
  • +
  • application/json
  • +
  • text/json
  • +
  • application/*+json
  • +
+ +

Request body

+
+
body JobDefinition (optional)
+ +
Body Parameter — The new job definition to run
+
+ + + + + + + + +

Produces

+ This API call produces the following media types according to the Accept request header; + the media type will be conveyed by the Content-Type response header. +
    +
  • application/json
  • +
+ +

Responses

+

200

+ Returns the newly created jobId + +

400

+ If there was an error in the request + inline_response_400 +
+
+

Webhooks

+
+
+ +
get /webhooks/v1/events
+
List all the supported event names.
+
+ + + + + + + + + + + + +

Responses

+

200

+ Success + +
+
+
+
+ +
get /webhooks/v1
+
List the webhooks associated with the tag. Optionally provide an event in the query string to just show that one event.
+
Sample response: +{ +"WebhookName" : "fooTag" +"Event" : "BugFound" +"TargetUrl" : "https://mywebhookreceiver" +}
+ + + + + +

Query parameters

+
+
name (optional)
+ +
Query Parameter — Name of the webhook "tag"
event (optional)
+ +
Query Parameter — Optional query string identifying the event
+ + + + + + + +

Responses

+

200

+ Returns success. + +

400

+ If the event name in the query string is not a supported value + +

404

+ If the webhook tag is not found + +
+
+
+
+ +
post /webhooks/v1
+
Associates a webhook "tag" with an event and target URL
+
Sample response: +{ +"WebhookName" : "fooTag" +"Event" : "BugFound" +"TargetUrl" : "https://mywebhookreceiver" +}
+ + +

Consumes

+ This API call consumes the following media types via the Content-Type request header: +
    +
  • application/json-patch+json
  • +
  • application/json
  • +
  • text/json
  • +
  • application/*+json
  • +
+ +

Request body

+
+
body WebHook (optional)
+ +
Body Parameter — A WebHook data type
+
+ + + + + + + + + +

Responses

+

200

+ Returns success. + +

400

+ Returns bad request if an exception occurs. The exception text will give the reason for the failure. + +
+
+
+
+ +
put /webhooks/v1
+
Associates a webhook "tag" with an event and target URL
+
Sample response: +{ +"WebhookName" : "fooTag" +"Event" : "BugFound" +"TargetUrl" : "https://mywebhookreceiver" +}
+ + +

Consumes

+ This API call consumes the following media types via the Content-Type request header: +
    +
  • application/json-patch+json
  • +
  • application/json
  • +
  • text/json
  • +
  • application/*+json
  • +
+ +

Request body

+
+
body WebHook (optional)
+ +
Body Parameter — A WebHook data type
+
+ + + + + + + + + +

Responses

+

200

+ Returns success. + +

400

+ Returns bad request if an exception occurs. The exception text will give the reason for the failure. + +
+
+
+
+ +
put /webhooks/v1/test/{webhookName}/{eventName}
+
+
+ +

Path parameters

+
+
webhookName (required)
+ +
Path Parameter
eventName (required)
+ +
Path Parameter
+ + + + + + + + + + + +

Responses

+

200

+Success + +
+
+
+
+ +
delete /webhooks/v1/{webhookName}/{eventName}
+
Delete the webhook for a specific event
+
If the name or event are not found, no error is returned.
+ +

Path parameters

+
+
webhookName (required)
+ +
Path Parameter — Name of the webhook tag
eventName (required)
+ +
Path Parameter — Name of the event
+ + + + + + + + + + + +

Responses

+

200

+ Returns success. + +

400

+ If the event name is not a supported value. + +
+
+ +

Models

+ [ Jump to Methods ] + +

Table of Contents

+
    +
  1. AgentConfiguration
  2. +
  3. AuthorizationToken
  4. +
  5. AzureADConfig
  6. +
  7. CommandLine
  8. +
  9. CompileConfiguration
  10. +
  11. CustomDictionary
  12. +
  13. FilePath
  14. +
  15. FileShareMount
  16. +
  17. JobDefinition
  18. +
  19. MSALConfig
  20. +
  21. ProblemDetails
  22. +
  23. RESTler
  24. +
  25. RaftTask
  26. +
  27. ReplayConfiguration
  28. +
  29. RunConfiguration
  30. +
  31. TargetEndpointConfiguration
  32. +
  33. TxtToken
  34. +
  35. Url
  36. +
  37. ValidationProblemDetails
  38. +
  39. WebHook
  40. +
  41. ZAP - ZAP
  42. +
  43. inline_response_400
  44. +
+ +
+

AgentConfiguration

+
Configure behaviour of RESTler agent
+
+
resultsAnalyzerReportTimeSpanInterval (optional)
String How often to run result analyzer against RESTler logs. Default is every 1 minute. +If not set then result analyzer will run only once after RESTler task is over. format: date-span
+
+
+
+

AuthorizationToken

+
Method of retrieving authorization token for the service under test
+
+
refreshIntervalSeconds (optional)
Integer Token Refresh Interval (default every 5 minutes) format: int32
+
tokenRefreshCommand (optional)
Token refresh command
+
oneOf: + AzureADConfig    + MSALConfig    + TxtToken    + CommandLine    +
+
+
+
+

AzureADConfig

+
Get authorization token from Azure AD using Service Principal
+
+
$type
+
secretName (optional)
String Key vault secret name that contains the MSAL configuration in JSON format +{ "tenant" : "<tenantId>", "client" : "<clientid>", "secret" : "<secret>" }
+
+
+
+

CommandLine

+
User specified command line to execute for acquiring authorization token
+
+
$type
+
command (optional)
String Command line to execute
+
+
+
+

CompileConfiguration

+
User-specified RESTler compiler configuration
+
+
compileJsonGrammar (optional)
String Relative path to a JSON grammar to use for compilation relative to compile folder path +If set then JSON grammar used for compilation instead of Swagger
+
compileFolderPath (optional)
String Grammar is produced by compile step prior. The compile step +file share is mounted and set here. Agent will not modify +this share. Agent will make a copy of all needed files to it's work directory +and re-run compile with data passed through this folder.
+
readOnlyFuzz (optional)
Boolean When true, only fuzz the GET requests
+
allowGetProducers (optional)
Boolean Allows GET requests to be considered. +This option is present for debugging, and should be +set to 'false' by default. +In limited cases when GET is a valid producer, the user +should add an annotation for it.
+
staticToken (optional)
String Token that can be used for authenticating with service under test
+
useRefreshableToken (optional)
Boolean Use refreshable token for authenticating with service under test
+
mutationsSeed (optional)
Long Use the seed to generate random value for empty/null customDictitonary fields +if not set then default hard-coded RESTler values are used for populating customDictionary fields format: int64
+
customDictionary (optional)
+
+
+
+

CustomDictionary

+ +
+
fuzzableString (optional)
array[String] List of string values used as fuzzing inputs. If null then values are auto-generated
+
fuzzableInt (optional)
array[String] List of int values used as fuzzing inputs. If null then values are auto-generated
+
fuzzableNumber (optional)
array[String] List of number values used as fuzzing inputs. If null then values are auto-generated
+
fuzzableBool (optional)
array[String] List of bool values used as fuzzing inputs. If null then values are auto-generated
+
fuzzableDatetime (optional)
array[String] List of date-time values used as fuzzing inputs. If null then values are auto-generated
+
fuzzableObject (optional)
array[String] List of string encoded JSON objects values used as fuzzing inputs
+
fuzzableUuid4 (optional)
array[String] List of UUID4 values used as fuzzing inputs
+
customPayload (optional)
map[String, array[String]] Map of values to use as replacement of parameters defined in Swagger specifications. For example +if { "userId" : ["a", "b"] } is specified then {userId} in URL path /users/{userId} will be replaced +by "a" or by "b"
+
customPayloadUuid4Suffix (optional)
map[String, String] Map of values to use as replacement of parameters defined in swagger. The values will +have a random suffix added. For example {"publicIpAddressName": "publicIpAddrName-"} will produce publicIpAddrName-f286a0a069 for +publicIpAddressName parameter defined in Swagger specifications.
+
customPayloadHeader (optional)
map[String, array[String]] User specified custom headers to pass in every request
+
shadowValues (optional)
map[String, map[String, array[String]]] RESTler documentation will have more info on this
+
+
+
+

FilePath

+
File path to Swagger specification
+
+
$type
+
value (optional)
String File path
+
+
+
+

FileShareMount

+
Mount file share from RAFT storage account to container running a payload.
+
+
fileShareName (optional)
String Any fileShare name from the RAFT storage account
+
mountPath (optional)
String Directory name under which file share is mounted on the container. For example "/my-job-config"
+
+
+
+

JobDefinition

+
RAFT job run definition
+
+
swagger (optional)
Swagger specification location for the job run
+
oneOf: + Url    + FilePath    +
+
namePrefix (optional)
String String used as a prefix added to service generated job ID. +Prefix can contain only lowercase letters, numbers, and hyphens, and must begin with a letter or a number. +Prefix cannot contain two consecutive hyphens. +Can be up to 27 characters long
+
tasks (optional)
array[RaftTask] RAFT Task definitions
+
duration (optional)
String Duration of the job; if not set, then job runs till completion (or forever). +For RESTler jobs - time limit is only useful for Fuzz task format: date-span
+
host (optional)
String Override the Host for each request.
+
webhook (optional)
String Webhook to associate with the job
+
metadata (optional)
map[String, String] Arbitrary key/value pairs that will be returned in webhooks
+
rootFileShare (optional)
String If set, then place all job run results into this file share
+
readOnlyFileSharesMounts (optional)
array[FileShareMount] File shares to mount from RAFT deployment storage account as read-only directories.
+
readWriteFileSharesMounts (optional)
array[FileShareMount] File shares to mount from RAFT deployment storage account as read-write directories.
+
+
+
+

MSALConfig

+
Get authorization token using MSAL. Uses .default for scope.
+
+
$type
+
secretName (optional)
String Key vault secret name that contains the MSAL configuration in JSON format +{ "tenant" : "<tenantId>", "client" : "<clientid>", "secret" : "<secret>" }
+
+
+
+

ProblemDetails

+ +
+
+
+
+

RESTler

+
RESTler payload
+
+
task (optional)
String Can be compile, fuzz, test, replay
+
compileConfiguration (optional)
+
runConfiguration (optional)
+
replayConfiguration (optional)
+
agentConfiguration (optional)
+
+
+
+

RaftTask

+
RAFT task to run.
+
+
toolName (optional)
String Tool defined by folder name located in cli/raft-utils/tools/{ToolName}
+
nameSuffix (optional)
String User assigned string appended to agent name, and agent generated results folder. +Must not contain: /*?:|&lt;&gt;"
+
swagger (optional)
Override swagger specification location
+
oneOf: + Url    + FilePath    +
+
host (optional)
String Override the Host for each request.
+
isIdling (optional)
Boolean Is this container idled and waiting for user to connect
+
duration (optional)
String Duration of the task; if not set, then job level duration is used. +For RESTler jobs - time limit is only useful for Fuzz task format: date-span
+
authTokenConfiguration (optional)
+
keyVaultSecrets (optional)
array[String] List of names of secrets in Keyvault used in configuring +authentication credentials +Key Vault secret name must start with alphabetic character and +followed by a string of alphanumeric characters (for example 'MyName123'). +Secret name can be upto 127 characters long
+
taskConfiguration (optional)
+
anyOf: + RESTler    +
+
+
+
+

ReplayConfiguration

+
RESTler configuration for replaying request sequences that triggered a reproducable bug
+
+
replayBugBucketsPaths (optional)
array[String] List of paths to RESTler folder runs to replay (names of folders are assigned when mounted readonly/readwrite file share mounts). +If path is a folder, then all bug buckets replayed in the folder. +If path is a bug_bucket file - then only that file is replayed. +If empty - then replay all bugs under RunConfiguration.previousStepOutputFolderPath.
+
runConfiguration (optional)
+
+
+
+

RunConfiguration

+
RESTler job Test, Fuzz or Replay configuration
+
+
grammarPy (optional)
String Path to grammar py relative to compile folder path. If not set then default "grammar.py" grammar is assumed
+
previousStepOutputFolderPath (optional)
String For Test or Fuzz tasks: Grammar is produced by compile step. The compile step +file share is mounted and set here. Agent will not modify +this share. Agent will make a copy of all needed files to it's work directory. +For Replay task: path to RESTler Fuzz or Test run that contains bug buckets to replay
+
targetEndpointConfiguration (optional)
+
producerTimingDelay (optional)
Integer The delay in seconds after invoking an API that creates a new resource format: int32
+
useSsl (optional)
Boolean Use SSL when connecting to the server
+
pathRegex (optional)
String Path regex for filtering tested endpoints
+
+
+
+

TargetEndpointConfiguration

+
Configuration of the endpoint under test
+
+
ip (optional)
String The IP of the endpoint being fuzzed
+
port (optional)
Integer The port of the endpoint being fuzzed. Defaults to 443. format: int32
+
+
+
+

TxtToken

+
Use static authorization token defined in a text file
+
+
$type
+
secretName (optional)
String Key vault secret name that contains the token as the secret value
+
+
+
+

Url

+
URL to Swagger specification
+
+
$type
+
value (optional)
String URL
+
+
+ +
+

WebHook

+ +
+
webhookName (optional)
+
event (optional)
+
targetUrl (optional)
String format: uri
+
+
+
+

ZAP - ZAP

+ +
+
+
+ + + diff --git a/docs/troubleshooting/idle.md b/docs/troubleshooting/idle.md new file mode 100644 index 0000000..05594fe --- /dev/null +++ b/docs/troubleshooting/idle.md @@ -0,0 +1,44 @@ +# How to SSH to a container + +When you need to look at see what is happening on a container to look at logs, +or to try out commands, see environment variables, etc use SSH or the shell availble +on the container through the portal. + +When adding a tool to use in the system, or using an existing tool, you can find +the commands used to run the tool in the `cli/raft-utils/tools` folder. Each +tool has a `config.json` file that defines the command to run when launching +a job and also a command to run when the tool configuration value `isIdle` is set to `true`. + +For example, the following would start /bin/sh and wait. + +``` + "idle" : { + "command" : "/bin/sh", + "arguments" : ["-c", "echo DebugMode; while true; do sleep 100000; done;"] + } +``` + +Using the [azure portal](https://azure.portal.com) navigate to the resource group where +the service is deployed. Once a job is created you will be able to see the container +instance in the resource group. The name of the resource is the same as the job id. + +For example:
+![](../images/containerInstanceInPortal.jpg)
+Here the value `2cf517a1-ed50-42bf-b713-d3d98bbcc0c0` is the job id. + +Click on the container and select the "Containers" tab. + +![](../images/containersTab.jpg) + +Click on the connect tab and the shell you want to invoke on the container. In this example +/bin/sh is selected. + +![](../images/connect.png) + +Once connected use the /bin/sh commands to navigate the system. + +![](../images/terminalExample.jpg) + +Note that once a container is launched in `isIdle` mode, the container instance +will need to be deleted either with the CLI delete command, or through the portal. The +service will not automatically garbage collect these containers. \ No newline at end of file diff --git a/docs/webhooks/creating.md b/docs/webhooks/creating.md new file mode 100644 index 0000000..8792961 --- /dev/null +++ b/docs/webhooks/creating.md @@ -0,0 +1,5 @@ +# Creating webhooks + +To create a webhook in the CLI use the `webhook-create` parameter. + +` python raft.py webhook-create --event [JobStatus | BugFound] --url ""` \ No newline at end of file diff --git a/docs/webhooks/deleting.md b/docs/webhooks/deleting.md new file mode 100644 index 0000000..c5f0fc4 --- /dev/null +++ b/docs/webhooks/deleting.md @@ -0,0 +1,7 @@ +# Deleting a webhook + +To delete a webhook in the CLI use the `webhook-delete` parameter. + +` python raft.py webhook-delete --event [JobStatus | BugFound]` + +It's required to provide the webhookName and the event you wish to delete. There is not a way to delete the webhook name without specifing the event. Once the last event has been deleted the domain topic is removed. diff --git a/docs/webhooks/overview.md b/docs/webhooks/overview.md new file mode 100644 index 0000000..8710c34 --- /dev/null +++ b/docs/webhooks/overview.md @@ -0,0 +1,24 @@ +# Webhooks overview + +Webhooks are managed in the system by an [Azure Event Grid Domain](https://docs.microsoft.com/en-us/azure/event-grid/event-domains). + +Looking at the resources created when you deploy the service you will see the Event Grid Domain with the name \-raft-events. + +Looking at the Event Grid Domain you will see a list of "Domain Topics" at the bottom of the overview tab. + +![](../images/webhook_demo.jpg) + +In this example the webhook name is "demo" + +When you click on the domain name, you will see the events that have been defined for it. + +When a webhook is created a name is associated with one or more events. The name is the domain topic. Each event under the domain topic +can have it's own target URL which is called when the event is fired. The events which are currently supported are: +* JobStatus +* BugFound + +The webhook name can be referenced in the [JobDefinition](../schema/jobdefinition.md) file in the webhook field. + +The webhook receiver must implement the [Endpoint validation protocol](https://docs.microsoft.com/en-us/azure/event-grid/webhook-event-delivery). +This allows the event grid to ensure that the target URL is a valid endpoint when it is established. Azure logic apps or Office 365 +flow events implement this protocol for you. \ No newline at end of file diff --git a/docs/webhooks/testing.md b/docs/webhooks/testing.md new file mode 100644 index 0000000..4e65497 --- /dev/null +++ b/docs/webhooks/testing.md @@ -0,0 +1,33 @@ +# Testing a webhook + +Once you have created a webhook, you might like to test it in order to verify your receiver is working correctly. + +To test a webhook in the CLI use the `webhook-test` parameter. + +` python raft.py webhook-test --event [JobStatus | BugFound]` + +Sending JobStatus dummy data via the test results in data that will look like this: + +``` +[{ + "id": "cef0cded-bd04-4fbe-a0a9-efb43c6564b7", + "eventType": "JobStatus", + "subject": "JobStatus", + "data": { + "tool": "RESTler", + "jobId": "webhook-test-job-status-3878d99e-33fb-4d2a-9f9f-4e29fb939ab9", + "state": "Running", + "utcEventTime": "2020-10-05T22:29:47.973649Z", + "details": ["WebhookV1-TestWebHook"], + "agentName": "1", + "isIdling": false + }, + "dataVersion": "1.0", + "metadataVersion": "1", + "eventTime": "2020-10-05T22:29:48.08349Z", + "topic": "/subscriptions/da3e8787-6e2b-4cae-b201-6e4cd71be189/resourceGroups/name-raft/providers/Microsoft.EventGrid/domains/name-raft-events/topics/demo" + } +] +``` + +In this data structure the `data` portion of the structure is unique to the service. The other information is standardized from the Event Grid. \ No newline at end of file diff --git a/src/APIService/APIService.sln b/src/APIService/APIService.sln new file mode 100644 index 0000000..6312d9e --- /dev/null +++ b/src/APIService/APIService.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29721.120 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "APIService", "ApiService\APIService.fsproj", "{F014D088-A287-47E3-984C-C90C7CE2CF8D}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "APIServiceTests", "ApiService\APIServiceTests\APIServiceTests.fsproj", "{834CB2AD-680B-41A0-A401-9C43CCD00750}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F014D088-A287-47E3-984C-C90C7CE2CF8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F014D088-A287-47E3-984C-C90C7CE2CF8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F014D088-A287-47E3-984C-C90C7CE2CF8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F014D088-A287-47E3-984C-C90C7CE2CF8D}.Release|Any CPU.Build.0 = Release|Any CPU + {834CB2AD-680B-41A0-A401-9C43CCD00750}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {834CB2AD-680B-41A0-A401-9C43CCD00750}.Debug|Any CPU.Build.0 = Debug|Any CPU + {834CB2AD-680B-41A0-A401-9C43CCD00750}.Release|Any CPU.ActiveCfg = Release|Any CPU + {834CB2AD-680B-41A0-A401-9C43CCD00750}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0D916CD3-0CB8-4A2D-A599-21D262740024} + EndGlobalSection +EndGlobal diff --git a/src/APIService/ApiService/APIService.fsproj b/src/APIService/ApiService/APIService.fsproj new file mode 100644 index 0000000..1f44281 --- /dev/null +++ b/src/APIService/ApiService/APIService.fsproj @@ -0,0 +1,78 @@ + + + + Exe + netcoreapp3.1 + apiservice + + + + true + $(NoWarn);1591 + + + + true + $(NoWarn);1591 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/APIService/ApiService/APIServiceTests/APIServiceTests.fsproj b/src/APIService/ApiService/APIServiceTests/APIServiceTests.fsproj new file mode 100644 index 0000000..48ea459 --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/APIServiceTests.fsproj @@ -0,0 +1,57 @@ + + + + netcoreapp3.1 + + false + false + + + + + Always + + + Always + + + Always + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + diff --git a/src/APIService/ApiService/APIServiceTests/DataStructuresConversions_Tests.fs b/src/APIService/ApiService/APIServiceTests/DataStructuresConversions_Tests.fs new file mode 100644 index 0000000..9eb9821 --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/DataStructuresConversions_Tests.fs @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +namespace DataStructuresConversionsTests + +open System.Collections.Generic +open FsCheck +open FsCheck.Xunit + +module DtoTypes = + open Raft.Controllers.DTOs + + let swaggerLocation = + Gen.oneof [ + gen { + let! s = Arb.generate> + return ({URL = s.Get; FilePath = null} : SwaggerLocation) + } + gen { + let! s = Arb.generate> + return ({URL = null; FilePath = s.Get}: SwaggerLocation) + } + ] + + let authenticationMethod = + Gen.oneof [ + gen { + let! s = Arb.generate> + return ({MSAL = s.Get; CommandLine = null; TxtToken = null}: AuthenticationMethod) + } + + gen { + let! s = Arb.generate> + return ({MSAL = null; CommandLine = s.Get; TxtToken = null}: AuthenticationMethod) + } + + gen { + let! s = Arb.generate> + return ({MSAL = null; CommandLine = null; TxtToken = s.Get}: AuthenticationMethod) + } + ] + + let fileShareMount = + gen { + let! fs = Arb.generate + let! m = Arb.generate + return ({FileShareName = fs.Get; MountPath = m.Get}:FileShareMount) + } + + let metadata = + gen { + let! m = Arb.generate> + let d: Dictionary = + m + |> Microsoft.FSharpLu.Json.Compact.serialize + |> Microsoft.FSharpLu.Json.Compact.deserialize + return d + } + + + let jObj = + gen { + return null + } + + type DtoGen = + static member ToolConfiguration() = + {new Arbitrary() with + override _.Generator = jObj + } + + static member AuthMethod() = + {new Arbitrary() with + override _.Generator = authenticationMethod + } + + static member SwaggerLocation() = + { new Arbitrary() with + override _.Generator = swaggerLocation + } + + static member FileShareMount() = + { new Arbitrary() with + override _.Generator = fileShareMount + } + + static member Metadata() = + { new Arbitrary>() with + override _.Generator = metadata + } + + +[ |] )>] +module Tests = + + let inline convert (j : ^T) = + j |> Microsoft.FSharpLu.Json.Compact.serialize |> Microsoft.FSharpLu.Json.Compact.deserialize + + [] + let ``Convert between internal and public datastructures``(dtoJobDefinition: Raft.Controllers.DTOs.JobDefinition)= + let internalJobDefinition : Raft.Job.JobDefinition = convert dtoJobDefinition + let dtoJobDefinition2 : Raft.Controllers.DTOs.JobDefinition = convert internalJobDefinition + let internalJobDefinition2 : Raft.Job.JobDefinition = convert dtoJobDefinition2 + + let s1 = dtoJobDefinition |> Microsoft.FSharpLu.Json.Compact.serialize + let s2 = dtoJobDefinition2 |> Microsoft.FSharpLu.Json.Compact.serialize + + let i1 = internalJobDefinition |> Microsoft.FSharpLu.Json.Compact.serialize + let i2 = internalJobDefinition2 |> Microsoft.FSharpLu.Json.Compact.serialize + + i1 = i2 && s1 = s2 + + + [] + let ``Convert between internal and public job request``(dtoJobRequest: Raft.Controllers.DTOs.CreateJobRequest) = + + let internalJobRequest : Raft.Job.CreateJobRequest = convert dtoJobRequest + let dtoJobRequest2 : Raft.Controllers.DTOs.CreateJobRequest = convert internalJobRequest + let internalJobRequest2 : Raft.Job.CreateJobRequest = convert dtoJobRequest2 + + let i1 = internalJobRequest |> Microsoft.FSharpLu.Json.Compact.serialize + let i2 = internalJobRequest2 |> Microsoft.FSharpLu.Json.Compact.serialize + + let d1 = dtoJobRequest |> Microsoft.FSharpLu.Json.Compact.serialize + let d2 = dtoJobRequest |> Microsoft.FSharpLu.Json.Compact.serialize + + i1 = i2 && d1 = d2 diff --git a/src/APIService/ApiService/APIServiceTests/Fixtures.fs b/src/APIService/ApiService/APIServiceTests/Fixtures.fs new file mode 100644 index 0000000..48dc66e --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/Fixtures.fs @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +namespace Raft.TestFixtures + +open Microsoft.Azure +open Microsoft.AspNetCore.Http +open Xunit +open NSubstitute +open Microsoft.Extensions.Configuration +open FSharp.Control.Tasks.V2 +open Microsoft.Azure.Cosmos.Table +open Raft.StorageEntities +open Microsoft.Extensions.Logging +open Microsoft.ApplicationInsights +open Microsoft.ApplicationInsights.Extensibility + +module Fixtures = + + let assertFailf format args = + let msg = sprintf format args + Assert.True(false, msg) + + let shouldContains actual expected = Assert.Contains(actual, expected) + let shouldEqual expected actual = Assert.Equal(expected, actual) + let shouldNotNull expected = Assert.NotNull(expected) + + let createFakeContext () = + Substitute.For() + + let createFakeConfiguration (configurationValueToReturn : string) = + let fakeConfiguration = Substitute.For() + let fakeSection = Substitute.For() + fakeSection.Value.ReturnsForAnyArgs(configurationValueToReturn) |> ignore + fakeConfiguration.GetSection("").ReturnsForAnyArgs(fakeSection) |> ignore + fakeConfiguration + + let createFakeMessageSender queue = + let fakeMessageSender = Substitute.For() + fakeMessageSender.SendAsync(Microsoft.Azure.ServiceBus.Message()).Returns(task {return()}) |> ignore + Raft.Utilities.serviceBusSenders <- Map.empty + .Add(queue, fakeMessageSender) + fakeMessageSender + + let createSerializerSettings() = + let settings = Newtonsoft.Json.JsonSerializerSettings() + settings.ContractResolver <- new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() + settings.Converters.Add(Newtonsoft.Json.Converters.StringEnumConverter()) + settings.Converters.Add(Microsoft.FSharpLu.Json.CompactUnionJsonConverter()) + settings.Formatting <- Newtonsoft.Json.Formatting.Indented + settings.NullValueHandling <- Newtonsoft.Json.NullValueHandling.Ignore + settings.DateTimeZoneHandling <- Newtonsoft.Json.DateTimeZoneHandling.Utc + settings.TypeNameHandling <- Newtonsoft.Json.TypeNameHandling.Auto + settings + + let createFakeRaftStorage (entity : JobStatusEntity option) = + let fakeRaftStorage = Substitute.For() + let fakeQuery = TableQuery().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, System.Guid.NewGuid().ToString())) + match entity with + | Some e -> (fakeRaftStorage.GetJobStatusEntities fakeQuery).ReturnsForAnyArgs(task { return seq {e} }) |> ignore + | None -> (fakeRaftStorage.GetJobStatusEntities fakeQuery).ReturnsForAnyArgs(task { return Seq.empty }) |> ignore + fakeRaftStorage + + let createFakeRaftStorageJobEnity (entity : JobEntity option) = + let fakeRaftStorage = Substitute.For() + match entity with + | Some e -> (fakeRaftStorage.TableEntryExists Raft.StorageEntities.JobTableName "jobId" "jobId").ReturnsForAnyArgs(task { return Result.Ok() }) |> ignore + | None -> (fakeRaftStorage.TableEntryExists Raft.StorageEntities.JobTableName "jobId" "jobId").ReturnsForAnyArgs(task { return Result.Error 400 }) |> ignore + fakeRaftStorage + + let createFakeLogger<'T> = Substitute.For>() + let createFakeTelemetryClient = TelemetryClient(new TelemetryConfiguration("")) diff --git a/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_DeleteJob.fs b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_DeleteJob.fs new file mode 100644 index 0000000..a5cdebc --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_DeleteJob.fs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace JobControllerTests + +open Xunit +open System.IO +open Raft.StorageEntities +open Raft.Controllers +open Raft.Errors +open Raft.TestFixtures + +[] +type DeleteJobTests() = + + [] + member this.``DELETE /jobs/restler fails on missing jobId`` () = + async { + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorage None + + let jobController = new jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! failedResult = jobController.Delete("thisJobDoesNotExist") |> Async.AwaitTask + let errorResult = failedResult.Value :?> ApiError + Assert.True(errorResult.Error.Code = ApiErrorCode.NotFound) + Assert.True(errorResult.Error.Message.Contains("thisJobDoesNotExist")) + } + + [] + member this.``DELETE /jobs/restler succeeds`` () = + async { + let fakeMessageSender = Fixtures.createFakeMessageSender Raft.Message.ServiceBus.Queue.delete + + let jobStatusJson = File.ReadAllText("job-status.json") + let entity = JobStatusEntity(System.Guid.Parse("29211868-8178-4e81-9b8d-d52025b4c2d4").ToString(), "testAgent", jobStatusJson) + + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorage (Some entity) + + let jobController = new jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! deleteResult = jobController.Delete "29211868-8178-4e81-9b8d-d52025b4c2d4" |> Async.AwaitTask + let result = deleteResult.Value :?> DTOs.CreateJobResponse + + let parseResult, jobGuid = System.Guid.TryParse(result.JobId) + Assert.True(parseResult) + Assert.True(jobGuid.ToString() = "29211868-8178-4e81-9b8d-d52025b4c2d4" ) + } + + diff --git a/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_GetJobStatus.fs b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_GetJobStatus.fs new file mode 100644 index 0000000..d82ec18 --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_GetJobStatus.fs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace JobControllerTests + +open Xunit +open System.IO +open Raft.StorageEntities +open System +open Raft.TestFixtures +open Raft.Controllers +open Raft.Errors + +[] +type GetJobStatusTests() = + + + [] + member this.``GET /jobs/restler fails on missing jobId`` () = + async { + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorage None + + let jobController = jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! failedResult = jobController.GetJobStatus "missingJobId" |> Async.AwaitTask + let errorResult = failedResult.Value :?> ApiError + Assert.True(errorResult.Error.Code = ApiErrorCode.NotFound) + Assert.True(errorResult.Error.Message.Contains("missingJobId")) + } + + [] + member this.``GET /jobs/restler succeeds`` () = + async { + let jobStatusJson = File.ReadAllText("job-status.json") + let entity = JobStatusEntity(Guid.Parse("29211868-8178-4e81-9b8d-d52025b4c2d4").ToString(), "29211868-8178-4e81-9b8d-d52025b4c2d4", jobStatusJson) + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorage (Some entity) + + let jobController = jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! result = jobController.GetJobStatus "29211868-8178-4e81-9b8d-d52025b4c2d4" |> Async.AwaitTask + let jobStatusSeq = result.Value :?> seq + let jobStatus = Seq.head jobStatusSeq + Assert.True(jobStatus.AgentName = "1") + Assert.True(jobStatus.Tool = "RESTler") + Assert.True(jobStatus.State = DTOs.JobState.Completed) + let testTimeUtc = DateTime.Parse("2020-05-01T00:36:56.7525482Z").ToUniversalTime() + Assert.True(DateTime.Compare(jobStatus.UtcEventTime, testTimeUtc) = 0) + } + + diff --git a/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_Info.fs b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_Info.fs new file mode 100644 index 0000000..6f23d48 --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_Info.fs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +namespace InfoControllerTests + +open Xunit +open Raft.Controllers +open Microsoft.AspNetCore.Mvc +open Raft.TestFixtures + +[] +type infoControllerTests() = + + [] + member this.``GET / should returns the correct response`` () = + + let infoController = new infoController(Fixtures.createFakeConfiguration "") + infoController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + let result = infoController.Get() + Assert.IsType(EmptyResult().GetType(), result) + + [] + member this.``GET /info should returns the correct response`` () = + let testDateTime = System.DateTimeOffset.Parse("7/27/2020 1:57:15 PM") + + let infoController = new infoController(Fixtures.createFakeConfiguration (testDateTime.ToString())) + infoController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let result = (infoController.GetInfo().Value) :?> infoType + Assert.True(result.ServiceStartTime = testDateTime) diff --git a/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_ListJobStatuses.fs b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_ListJobStatuses.fs new file mode 100644 index 0000000..e9e1a27 --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_ListJobStatuses.fs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace JobControllerTests + +open Xunit +open System.IO +open Raft.StorageEntities +open System +open Raft.TestFixtures +open Raft.Controllers + +[] +type ListJobStatusesTests() = + + [] + member this.``LIST /jobs/restler succeeds with zero status objects`` () = + async { + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorage None + + let jobController = jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! results = jobController.List Unchecked.defaultof<_> |> Async.AwaitTask + let seqResults = results.Value :?> seq + Assert.True(Seq.isEmpty seqResults) + } + + [] + member this.``LIST /jobs/restler succeeds`` () = + async { + let jobStatusJson = File.ReadAllText("job-status.json") + let entity = JobStatusEntity(Guid.Parse("29211868-8178-4e81-9b8d-d52025b4c2d4").ToString(), "testAgent", jobStatusJson) + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorage (Some entity) + + let jobController = jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! results = jobController.List (Nullable(TimeSpan.FromHours(4.0))) |> Async.AwaitTask + let seqResults = results.Value :?> seq + Assert.True(Seq.length seqResults = 1) + } + diff --git a/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_PostJob.fs b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_PostJob.fs new file mode 100644 index 0000000..08c0cef --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_PostJob.fs @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace JobControllerTests + +open Xunit +open System.IO +open Raft.Controllers +open Raft.TestFixtures +open Raft.Errors + +[] +type jobsPOSTTests() = + + [] + member this.``POST /jobs compile job`` () = + async { + let fakeMessageSender = Fixtures.createFakeMessageSender Raft.Message.ServiceBus.Queue.create + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorage None + + let contents = File.ReadAllText("grade-track-restler-compile.json") + let compileJobDefinition = Newtonsoft.Json.JsonConvert.DeserializeObject(contents, Fixtures.createSerializerSettings()) + + let jobController = jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! jobResult = jobController.Post("", compileJobDefinition) |> Async.AwaitTask + let result = jobResult.Value :?> DTOs.CreateJobResponse + Assert.True(result.JobId.StartsWith("grade-track-compile-")) + + let parseResult, jobGuid = System.Guid.TryParse(result.JobId.Substring("grade-track-compile-".Length)) + Assert.True(parseResult) + } + + [] + member this.``POST /jobs fuzz job`` () = + async { + let fakeMessageSender = Fixtures.createFakeMessageSender Raft.Message.ServiceBus.Queue.create + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorage None + + let contents = File.ReadAllText("grade-track-restler-fuzz.json") + let fuzzJobDefinition = Newtonsoft.Json.JsonConvert.DeserializeObject(contents, Fixtures.createSerializerSettings()) + + let jobController = jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! jobResult = jobController.Post("", fuzzJobDefinition) |> Async.AwaitTask + let result = jobResult.Value :?> DTOs.CreateJobResponse + + let parseResult, jobGuid = System.Guid.TryParse(result.JobId) + Assert.True(parseResult) + } + + [] + member this.``POST /jobs compile job with empty payload`` () = + async { + let fakeMessageSender = Fixtures.createFakeMessageSender Raft.Message.ServiceBus.Queue.create + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorage None + + let contents = File.ReadAllText("grade-track-restler-compile.json") + let compileJobDefinition = Newtonsoft.Json.JsonConvert.DeserializeObject(contents, Fixtures.createSerializerSettings()) + let compileJobDefinition = + { + compileJobDefinition with + Tasks = Array.empty + } + + let jobController = jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! failedResult = jobController.Post("", compileJobDefinition) |> Async.AwaitTask + let errorResult = failedResult.Value :?> ApiError + Assert.True(errorResult.Error.Code = ApiErrorCode.ParseError) + } \ No newline at end of file diff --git a/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_RePostJob.fs b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_RePostJob.fs new file mode 100644 index 0000000..b5e17f9 --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/JobVerb_Tests_RePostJob.fs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace JobControllerTests + +open Xunit +open System.IO +open Raft.Controllers +open Raft.TestFixtures +open Raft.Errors + +[] +type jobsRePOSTTests() = + + [] + member this.``Re-POST /jobs compile job`` () = + async { + let fakeMessageSender = Fixtures.createFakeMessageSender Raft.Message.ServiceBus.Queue.create + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorage None + + let contents = File.ReadAllText("grade-track-restler-compile.json") + let compileJobDefinition = Newtonsoft.Json.JsonConvert.DeserializeObject(contents, Fixtures.createSerializerSettings()) + + let jobController = jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! jobResult = jobController.RePost("29211868-8178-4e81-9b8d-d52025b4c2d4", compileJobDefinition) |> Async.AwaitTask + let rePostResult = jobResult.Value :?> DTOs.CreateJobResponse + + let parseResult, jobGuid = System.Guid.TryParse(rePostResult.JobId) + Assert.True(parseResult) + Assert.True(jobGuid.ToString() = "29211868-8178-4e81-9b8d-d52025b4c2d4" ) + } + + [] + member this.``Re-POST /jobs fail because jobId does not exist`` () = + async { + let fakeMessageSender = Fixtures.createFakeMessageSender Raft.Message.ServiceBus.Queue.create + Raft.Utilities.raftStorage <- Fixtures.createFakeRaftStorageJobEnity None + + let contents = File.ReadAllText("grade-track-restler-compile.json") + let compileJobDefinition = Newtonsoft.Json.JsonConvert.DeserializeObject(contents, Fixtures.createSerializerSettings()) + + let jobController = jobsController(Fixtures.createFakeTelemetryClient, Fixtures.createFakeLogger) + jobController.ControllerContext.HttpContext <- Fixtures.createFakeContext() + + let! failedResult = jobController.RePost("29211868-8178-4e81-9b8d-d52025b4c2d4", compileJobDefinition) |> Async.AwaitTask + let errorResult = failedResult.Value :?> ApiError + Assert.True(errorResult.Error.Code = ApiErrorCode.NotFound) + } + + \ No newline at end of file diff --git a/src/APIService/ApiService/APIServiceTests/Program.fs b/src/APIService/ApiService/APIServiceTests/Program.fs new file mode 100644 index 0000000..0695f84 --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/Program.fs @@ -0,0 +1 @@ +module Program = let [] main _ = 0 diff --git a/src/APIService/ApiService/APIServiceTests/grade-track-restler-compile.json b/src/APIService/ApiService/APIServiceTests/grade-track-restler-compile.json new file mode 100644 index 0000000..9c33e07 --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/grade-track-restler-compile.json @@ -0,0 +1,37 @@ +{ + "swaggerLocation": { + "URL": "https://a-test-service.azurewebsites.net/swagger/v1/swagger.json" + }, + "NamePrefix": "grade-track-compile-", + "host": "a-test-service.azurewebsites.net", + + "webhook": { + "name" : "test-webhook", + "metadata": { + "build": "1.5", + "owner": "me" + } + }, + "tasks": [ + { + "toolName": "RESTler", + "isIdling": false, + "outputFolder": "RESTler-Compile1", + "toolConfiguration": { + "task": "Compile" + } + }, + { + "toolName": "RESTler", + "isIdling": false, + "outputFolder": "RESTler-Compile2", + + "toolConfiguration": { + "task": "Compile", + "compileConfiguration": { + "mutationsSeed": 34534798 + } + } + } + ] +} diff --git a/src/APIService/ApiService/APIServiceTests/grade-track-restler-fuzz.json b/src/APIService/ApiService/APIServiceTests/grade-track-restler-fuzz.json new file mode 100644 index 0000000..ef6466f --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/grade-track-restler-fuzz.json @@ -0,0 +1,61 @@ +{ + "swaggerLocation": { + "URL" : "https://a-test-service.azurewebsites.net/swagger/v1/swagger.json" + }, + "duration": "00:10:00", + "host": "a-test-service.azurewebsites.net", + "tasks": [ + { + "toolName": "RESTler", + "outputFolder": "RESTler-fuzz-1", + "toolConfiguration": { + "task": "Fuzz", + + "agentConfiguration": { + "resultsAnalyzerReportTimeSpanInterval": "00:01:00" + }, + "runConfiguration": { + "inputFolderPath": "/job-compile/0-RESTler-Compile", + "useSsl": true, + "producerTimingDelay": 5 + } + } + }, + { + "toolName": "RESTler", + "outputFolder": "RESTler-fuzz-2", + "toolConfiguration": { + "task": "Fuzz", + "agentConfiguration": { + "resultsAnalyzerReportTimeSpanInterval": "00:01:00" + }, + + "runConfiguration": { + "inputFolderPath": "/job-compile/0-RESTler-Compile", + "useSsl": true, + "producerTimingDelay": 2 + } + } + }, + { + "toolName": "RESTler", + "outputFolder": "RESTler-fuzz-3", + "toolConfiguration": { + "task": "Fuzz", + "agentConfiguration": { + "resultsAnalyzerReportTimeSpanInterval": "00:01:00" + }, + + "runConfiguration": { + "inputFolderPath": "/job-compile/1", + "useSsl": true, + "producerTimingDelay": 5, + "targetEndpointConfiguration": { + "ip": "13.77.182.13", + "port": "443" + } + } + } + } + ] +} diff --git a/src/APIService/ApiService/APIServiceTests/grade-track.json b/src/APIService/ApiService/APIServiceTests/grade-track.json new file mode 100644 index 0000000..9c25460 --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/grade-track.json @@ -0,0 +1,28 @@ +{ + "tool": "RESTler", + "jobConfig": { + "swaggerJsonUrl": "https://a-test-service.azurewebsites.net/swagger/v1/swagger.json", + "targetPort": "443", + "producerTimingDelay": 5, + "useSsl": true, + "host": "a-test-service.azurewebsites.net", + "pathRegex": null, + "duration": "00:06:00", + "TargetUri": "https://a-test-service.azurewebsites.net" + }, + "customDictionary": { + "fuzzableString": [], + "fuzzableInt": [], + "fuzzableNumber": [], + "fuzzableBool": [], + "fuzzableDatetime": [], + "fuzzableObject": [], + "fuzzableUuid4": [], + "args": {} + }, + "fuzzingConfiguration": { + "readOnlyFuzz": false, + "staticToken": null, + "allowGetProducers": false + } +} diff --git a/src/APIService/ApiService/APIServiceTests/job-status.json b/src/APIService/ApiService/APIServiceTests/job-status.json new file mode 100644 index 0000000..f5dbb34 --- /dev/null +++ b/src/APIService/ApiService/APIServiceTests/job-status.json @@ -0,0 +1,16 @@ +{ + "message": { + "tool": "RESTler", + "jobId": "29211868-8178-4e81-9b8d-d52025b4c2d4", + "state": "Completed", + "metrics": { + "totalRequestCount": 60, + "responseCodeCounts": { "409": 60 }, + "totalBugBucketsCount": 0 + }, + "utcEventTime": "2020-05-01T00:36:56.7525482Z", + "details": [], + "agentName": "1" + } +} + diff --git a/src/APIService/ApiService/Constants.fs b/src/APIService/ApiService/Constants.fs new file mode 100644 index 0000000..57c460d --- /dev/null +++ b/src/APIService/ApiService/Constants.fs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft + +module Constants = + + let DateTimeQueryStringNameFilter = "filter" + let StorageTableConnectionString = "RAFT_STORAGE_TABLE_CONNECTION_STRING" + let JobStatusTableName = "JobStatus" + let ServiceBusConnectionStringSetting = "RAFT_SERVICEBUS_SEND_CONNECTION_STRING" + let PartitionKey = "PartitionKey" + let Timestamp = "Timestamp" + diff --git a/src/APIService/ApiService/Controllers/Info.fs b/src/APIService/ApiService/Controllers/Info.fs new file mode 100644 index 0000000..0c52a1a --- /dev/null +++ b/src/APIService/ApiService/Controllers/Info.fs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft.Controllers + +open Microsoft.AspNetCore.Mvc +open Raft.Telemetry +open System.Reflection +open Microsoft.AspNetCore.Http +open Microsoft.Extensions.Configuration +open Raft.Telemetry.TelemetryApiService + +/// +/// Information about the system. +/// +type infoType = + { + /// + /// Version of the binary running on the server + /// + Version : System.Version + + /// + /// When the server started running. DateTimeOffset in UTC . + /// + ServiceStartTime : System.DateTimeOffset + } + +[] +[] +[] +type infoController (configuration : IConfiguration) = + inherit ControllerBase() + let ModuleName = "Info-" + + [] + /// + /// Test to see if service is up + /// + /// + /// This is an unauthenticated method which returns no data. + /// + /// Returns success if the service is running. + [] + member this.Get() = + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + + let method = ModuleName + "Get" + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest (method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + EmptyResult() + + [] + /// + /// Returns information about the system. + /// + /// + /// This is an unauthenticated method. + /// Sample response: + /// { + /// "version": "1.0.0.0", + /// "serviceStartTime": "2020-07-02T15:28:57.0093727+00:00" + /// } + /// + /// Returns success. + [] + member this.GetInfo() = + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + + let method = ModuleName + "GetInfo" + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + + let info = { + Version = Assembly.GetEntryAssembly().GetName().Version + ServiceStartTime = System.DateTimeOffset.Parse(configuration.GetValue("RestartTime")) + } + JsonResult(info) diff --git a/src/APIService/ApiService/Controllers/Job.fs b/src/APIService/ApiService/Controllers/Job.fs new file mode 100644 index 0000000..a10d896 --- /dev/null +++ b/src/APIService/ApiService/Controllers/Job.fs @@ -0,0 +1,532 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft.Controllers + +open System +open Microsoft.Azure.Cosmos.Table +open Raft.StorageEntities +open Raft.Telemetry +open Raft.Utilities +open Raft +open Raft.Controllers +open Microsoft.AspNetCore.Mvc +open FSharp.Control.Tasks.V2 +open Raft.Controllers.AppInsights +open Microsoft.ApplicationInsights +open System.Runtime.InteropServices +open Microsoft.AspNetCore.Authorization +open Raft.Errors +open Microsoft.Extensions.Logging +open Microsoft.AspNetCore.Http +open Raft.Telemetry.TelemetryApiService + +[] +[] +[] +[] +type jobsController(telemetryClient : TelemetryClient, logger : ILogger) = + inherit ControllerBase() + let ModuleName = "Job-" + let tags = ["Service", "WebhookService"] + let log = Log telemetryClient + + // Validation function to validate the job request + // If something does not validate, we want to throw an exception with a a standard error type + // that is informative for the customer. + let validateAndPatchPayload (requestPayload: DTOs.JobDefinition) = + if Array.isEmpty requestPayload.Tasks then + raiseApiError ({ + Error = + { + Code = ApiErrorCode.ParseError + Message = sprintf "Every job definition must define at least 1 task: %A" requestPayload + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + + let outputFolders = requestPayload.Tasks |> Array.map (fun t -> t.OutputFolder) |> Array.sort + + let requestPayload = + {requestPayload with + Tasks = + requestPayload.Tasks + |> Array.map (fun t -> + if isNull (box t.SwaggerLocation) then + { t with SwaggerLocation = requestPayload.SwaggerLocation } + else + t + ) + |> Array.map(fun t -> + if String.IsNullOrWhiteSpace t.Host then + { t with Host = requestPayload.Host } + else + t + ) + |> Array.map(fun t -> + if not t.Duration.HasValue then + { t with Duration = requestPayload.Duration } + else + t + ) + + Resources = + if isNull (box requestPayload.Resources) then + { + Cores = 1 + MemoryGBs = 1 + } + else + requestPayload.Resources + } + + + let taskAuthentication = + requestPayload.Tasks + |> Array.filter(fun t -> not <| isNull (box t.AuthenticationMethod)) + |> Array.map (fun t -> t.AuthenticationMethod) + + if requestPayload.Tasks.Length > requestPayload.Resources.MemoryGBs * 10 then + raiseApiError ({ + Error = + { + Code = ApiErrorCode.ParseError + Message = sprintf "Number of tasks must be less or equal to (MemoryGBs*10)" + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + + + taskAuthentication + |> Array.iter(fun auth -> + let enabled = + [ + not <| String.IsNullOrWhiteSpace auth.TxtToken + not <| String.IsNullOrWhiteSpace auth.CommandLine + not <| String.IsNullOrWhiteSpace auth.MSAL + ] + |> List.map (fun b -> if b then 1 else 0) + + if List.sum enabled > 1 then + raiseApiError ({ + Error = + { + Code = ApiErrorCode.ParseError + Message = sprintf "Only one type of Authentication method is allowed per task" + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + ) + + let duplicateFolders = + outputFolders + |> Array.pairwise + |> Array.filter (fun (f1, f2) -> f1.ToLowerInvariant() = f2.ToLowerInvariant()) + |> Array.map fst + + if not <| Array.isEmpty duplicateFolders then + raiseApiError ({ + Error = + { + Code = ApiErrorCode.InvalidJob + Message = sprintf "Output folders must be unique. Found duplicate folders: %A" duplicateFolders + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + + requestPayload.Tasks + |> Array.iter(fun t -> + let location = t.SwaggerLocation + if not <| String.IsNullOrWhiteSpace(location.URL) then + match Uri.TryCreate(location.URL, UriKind.Absolute) with + | true, _ -> () + | false, _ -> raiseApiError({ + Error = { + Code = ApiErrorCode.ParseError + Message = "Invalid Swagger Uri in a task. The Uri must be a valid, absolute Uri." + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + + if not <| String.IsNullOrWhiteSpace location.URL && + not <| String.IsNullOrWhiteSpace location.FilePath then + raiseApiError({ + Error = { + Code = ApiErrorCode.ParseError + Message = "Only one Swagger Location value is allowed in tasks: Path or URL but not both" + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + ) + if not <| isNull requestPayload.ReadOnlyFileShareMounts then + requestPayload.ReadOnlyFileShareMounts + |> Array.iter(fun fs -> + if String.IsNullOrWhiteSpace fs.FileShareName || String.IsNullOrWhiteSpace fs.MountPath then + raiseApiError({ + Error = { + Code = ApiErrorCode.ParseError + Message = "ReadOnlyFileShareMounts has to have non-null and non-empty FileShareName and MountPath" + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + ) + + if not <| isNull requestPayload.ReadWriteFileShareMounts then + requestPayload.ReadWriteFileShareMounts + |> Array.iter(fun fs -> + if String.IsNullOrWhiteSpace fs.FileShareName || String.IsNullOrWhiteSpace fs.MountPath then + raiseApiError({ + Error = { + Code = ApiErrorCode.ParseError + Message = "ReadWriteFileShareMounts has to have non-null and non-empty FileShareName and MountPath" + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + ) + + + //U+0000 to U+001F + //U+007F to U+009F + // '/' '\', '#', '?' + if not <| String.IsNullOrWhiteSpace requestPayload.NamePrefix && requestPayload.NamePrefix + |> Seq.exists (fun c -> (Char.IsControl c) || c = '/' || c = '\\' || c = '#' || c = '?' || c = '\t' || c = '\n' || c = '\r' ) then + raiseApiError({ + Error = { + Code = ApiErrorCode.ParseError + Message = "Name prefix contains disallowed character(s). Any of control characters or / \\ # ? \\t \\n \\r" + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + + if not <| isNull(box requestPayload.Webhook) then + if String.IsNullOrWhiteSpace requestPayload.Webhook.Name then + raiseApiError({ + Error = { + Code = ApiErrorCode.ParseError + Message = "Webhook name must be a non-empty string" + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + + // Validate the swagger URL. + if not <| String.IsNullOrWhiteSpace(requestPayload.SwaggerLocation.URL) then + match Uri.TryCreate(requestPayload.SwaggerLocation.URL, UriKind.Absolute) with + | true, _ -> () + | false, _ -> raiseApiError({ + Error = { + Code = ApiErrorCode.ParseError + Message = "Invalid Swagger Uri. The Uri must be a valid, absolute Uri." + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + + if not <| String.IsNullOrWhiteSpace(requestPayload.SwaggerLocation.URL) && + not <| String.IsNullOrWhiteSpace(requestPayload.SwaggerLocation.FilePath) then + raiseApiError({ + Error = { + Code = ApiErrorCode.ParseError + Message = "Only one Swagger Location value is allowed Path or URL but not both" + Target = "validateAndPatchPayload" + Details = Array.empty + InnerError = {Message = ""} + } + }) + + requestPayload + + [] + /// + /// Submit a job definition. + /// + /// + /// Run the job definition in a specified region. If not set - run in the same region as the service + /// https://docs.microsoft.com/en-us/azure/container-instances/container-instances-region-availability + /// + /// The new job definition to run + /// Returns the newly created jobId + /// If there was an error in the request + [, StatusCodes.Status200OK)>] + [, StatusCodes.Status400BadRequest)>] + member this.Post([] region : string, [] body : DTOs.JobDefinition ) = + task { + let stopWatch = System.Diagnostics.Stopwatch() + do stopWatch.Start() + + let method = ModuleName + "Post" + try + let createQueue = Raft.Message.ServiceBus.Queue.create + + let validatedPayload = validateAndPatchPayload body + + let jobId = sprintf "%s%O" (if String.IsNullOrWhiteSpace body.NamePrefix then String.Empty else body.NamePrefix.Trim()) (Guid.NewGuid()) + log.Info "Creating new job ID" ["method", method; "JobId", jobId; "region", region; "body", sprintf "%A" validatedPayload] + + let validatedBody : DTOs.CreateJobRequest = { JobId = jobId; JobDefinition = validatedPayload; IsIdlingRun = false; Region = region} + + if not (isNull (box validatedBody.JobDefinition.Webhook)) then + let tags = ["method", method; "JobId", jobId; "region", region; "webhook", validatedBody.JobDefinition.Webhook.Name] + log.Info "Configuring webhook" tags + + let entity = JobWebhookEntity(validatedBody.JobId, validatedBody.JobDefinition.Webhook.Name) :> TableEntity + log.Info "Inserting webhook entity" tags + match! Utilities.raftStorage.InsertEntity Raft.StorageEntities.JobWebHookTableName entity with + | Result.Ok() -> + log.Info "Successfully inserted webhook entity" tags + | Result.Error (statusCode) -> + let errorMessage = sprintf "Insert into %s failed. HttpStatusCode is %d. JobId is %O" Raft.StorageEntities.JobWebHookTableName statusCode validatedBody.JobId + log.Error errorMessage tags + raiseApiError ({ + Error = + { + Code = ApiErrorCode.InternalError + Message = "Insert into table failed" + Target = method + Details = Array.empty + InnerError = {Message = errorMessage} + } + }) + + log.Info "Posting job creation request to the orchestrator queue" ["method", method; "JobId", jobId; "region", region] + do! sendCommand createQueue validatedBody.JobId + { + Message = validatedBody + MessagePostCount = 0 + } + + let serializedWebhook = Newtonsoft.Json.JsonConvert.SerializeObject(validatedBody.JobDefinition.Webhook) + let entity = JobEntity(validatedBody.JobId, serializedWebhook) + + log.Info "Inserting job entity into job table" ["method", method; "JobId", jobId; "region", region] + match! Utilities.raftStorage.InsertEntity Raft.StorageEntities.JobTableName entity with + | Result.Ok() -> + log.Info "Successfully inserted job entity into job table" ["method", method; "JobId", jobId; "region", region] + | Result.Error (statusCode) -> + let errorMessage = sprintf "Insert into %s failed. HttpStatusCode is %d. JobId is %O" Raft.StorageEntities.JobTableName statusCode validatedBody.JobId + log.Error errorMessage ["method", method; "JobId", jobId; "region", region] + raiseApiError ({ + Error = + { + Code = ApiErrorCode.InternalError + Message = "Insert into table failed" + Target = method + Details = Array.empty + InnerError = {Message = errorMessage} + } + }) + + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + return JsonResult(DTOs.CreateJobResponse(JobId = validatedBody.JobId)) + with + | Errors.ApiErrorException (apiError) as ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + return setApiErrorStatusCode apiError Microsoft.AspNetCore.Http.StatusCodes.Status400BadRequest + } + + + //Move this to a separate controller ? something like ends with "/debug" ? + //Since this way of working with jobs is intended for fast iterations when doing initial setup of the job + [] + /// + /// Repost a job definition to an existing job. + /// + /// + /// The existing job must have been created with IsIdling set to true. + /// + /// The id which refers to an existing job + /// The new job definition to run + /// Returns the newly created jobId + /// If there was an error in the request + [, StatusCodes.Status200OK)>] + [, StatusCodes.Status400BadRequest)>] + member this.RePost(jobId: string, [] body : DTOs.JobDefinition ) = + task { + let stopWatch = System.Diagnostics.Stopwatch() + do stopWatch.Start() + + let method = ModuleName + "RePost" + + try + match! Utilities.raftStorage.TableEntryExists Raft.StorageEntities.JobTableName jobId jobId with + | Result.Ok() -> () + | Result.Error err -> + raiseApiError ({ + Error = + { + Code = ApiErrorCode.NotFound + Message = "JobId was not found. The jobId must already exist and have been created with the IsIdling flag set to true." + Target = method + Details = Array.empty + InnerError = {Message = sprintf "Job table search for %O failed with HttpStatus %d" jobId err} + } + }) + + + let createQueue = Raft.Message.ServiceBus.Queue.create + let validatedPayload = validateAndPatchPayload body + + let repost : DTOs.CreateJobRequest = {JobId = jobId; JobDefinition = validatedPayload; IsIdlingRun = true; Region = null} + + do! sendCommand createQueue repost.JobId {Message = repost; MessagePostCount = 0} + + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + return JsonResult(DTOs.CreateJobResponse(JobId = repost.JobId)) + with + | Errors.ApiErrorException (apiError) as ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + match apiError.Error.Code with + | ApiErrorCode.NotFound -> + return setApiErrorStatusCode apiError Microsoft.AspNetCore.Http.StatusCodes.Status404NotFound + | _ -> + return setApiErrorStatusCode apiError Microsoft.AspNetCore.Http.StatusCodes.Status400BadRequest + + } + + + /// + /// Deletes a job + /// + /// The id which refers to an existing job + /// Returns the newly created jobId + /// If the job was not found + [, StatusCodes.Status200OK)>] + [, StatusCodes.Status404NotFound)>] + [] + member this.Delete (jobId : string) = + task { + let stopWatch = System.Diagnostics.Stopwatch() + do stopWatch.Start() + + let method = ModuleName + "Delete" + + try + // Verify that we find a job with this jobId in the job status table. + let query = TableQuery().Where(TableQuery.GenerateFilterCondition(Constants.PartitionKey, QueryComparisons.Equal, jobId.ToString())) + let! results = raftStorage.GetJobStatusEntities query + if Seq.isEmpty results then + return raiseApiError { Error = { Code = ApiErrorCode.NotFound + Message = sprintf "Job status for job id %O not found." jobId + Target = method + Details = [||] + InnerError = {Message = ""} + }} + else + let message = DTOs.DeleteJobRequest(JobId = jobId) + + do! sendCommand Raft.Message.ServiceBus.Queue.delete jobId { Message = message; MessagePostCount = 0 } + + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + return JsonResult(DTOs.CreateJobResponse (JobId = jobId) ) + with + | Errors.ApiErrorException (apiError) as ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + return setApiErrorStatusCode apiError Microsoft.AspNetCore.Http.StatusCodes.Status404NotFound + } + + [] + /// + /// Returns status for the specified job. + /// + /// Returns the job status data + /// If the job was not found + [>, StatusCodes.Status200OK)>] + [, StatusCodes.Status404NotFound)>] + member this.GetJobStatus (jobId : string) = + task { + let stopWatch = System.Diagnostics.Stopwatch() + do stopWatch.Start() + + let method = ModuleName + "GetJobStatus" + + let query = TableQuery().Where(TableQuery.GenerateFilterCondition(Constants.PartitionKey, QueryComparisons.Equal, jobId)) + let! results = Utilities.raftStorage.GetJobStatusEntities query + if results |> Seq.tryFind (fun (r:JobStatusEntity) -> r.PartitionKey = r.RowKey) = None then + printfn "Results sequence is discarded since overall job status is not yet set after executing table query for job: %A" jobId + return setApiErrorStatusCode { Error = { Code = ApiErrorCode.NotFound + Message = sprintf "Job status for job id %O not found." jobId + Target = method + Details = [||] + InnerError = {Message = ""} + }} Microsoft.AspNetCore.Http.StatusCodes.Status404NotFound + else + let decodedMessages = + results + |> Seq.map (fun jobStatusEntity -> Raft.Message.RaftEvent.deserializeEvent jobStatusEntity.JobStatus) + |> Seq.map (fun jobStatus -> DTOs.JobStatus.FromInternal jobStatus.Message) + + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + return JsonResult(decodedMessages) + } + + + [] + /// + /// Returns in an array status for all jobs over the last 24 hours. + /// + /// + /// The default timespan is over the last 24 hours. Use the query string timeSpanFilter="TimeSpan" to specify a different interval. + /// Use a time format that can be parsed as a TimeSpan data type. + /// If no data is found the result will be an empty array. + /// + /// A string which is interpreted as a TimeSpan + /// Returns the job status data + [>, StatusCodes.Status200OK)>] + [, StatusCodes.Status404NotFound)>] + member this.List([] timeSpanFilter:Nullable) = + task { + let stopWatch = System.Diagnostics.Stopwatch() + do stopWatch.Start() + + let method = ModuleName + "List" + + let defaultTimeSpan = TimeSpan.FromDays(1.0) + let query = + if timeSpanFilter.HasValue then + TableQuery().Where( + TableQuery.GenerateFilterConditionForDate( + Constants.Timestamp, QueryComparisons.GreaterThanOrEqual, + DateTimeOffset.Now.Subtract(timeSpanFilter.Value))) + else + TableQuery().Where( + TableQuery.GenerateFilterConditionForDate( + Constants.Timestamp, QueryComparisons.GreaterThanOrEqual, + DateTimeOffset.Now.Subtract(defaultTimeSpan))) + + + let! result = Utilities.raftStorage.GetJobStatusEntities query + + let statuses : DTOs.JobStatus seq = result + |> Seq.map(fun (s: JobStatusEntity) -> Raft.Message.RaftEvent.deserializeEvent s.JobStatus) + |> Seq.map (fun jobStatus -> DTOs.JobStatus.FromInternal jobStatus.Message) + + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + return JsonResult(statuses) + } + + diff --git a/src/APIService/ApiService/Controllers/Webhook.fs b/src/APIService/ApiService/Controllers/Webhook.fs new file mode 100644 index 0000000..7479176 --- /dev/null +++ b/src/APIService/ApiService/Controllers/Webhook.fs @@ -0,0 +1,451 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft.Controllers +// +// https://docs.microsoft.com/en-us/azure/event-grid/post-to-custom-topic +// https://github.com/Azure-Samples/event-grid-dotnet-publish-consume-events/blob/master/EventGridPublisher/TopicPublisher/Program.cs + +open System +open Raft.Webhooks +open Raft.Controllers.AppInsights +open Microsoft.Azure.Management.EventGrid +open Microsoft.Azure.EventGrid +open Microsoft.Azure.Management.ResourceManager.Fluent +open Microsoft.Rest.Azure +open Raft.JobEvents +open Raft.Utilities +open Raft +open Microsoft.AspNetCore.Mvc +open Microsoft.Extensions.Configuration +open FSharp.Control.Tasks.V2 +open Microsoft.ApplicationInsights +open Raft.Telemetry +open Microsoft.AspNetCore.Authorization +open Raft.Errors +open Microsoft.Extensions.Logging +open Raft.Telemetry.TelemetryApiService +open Microsoft.Azure.Cosmos.Table + +[] +[] +[] +[] +type webhooksController(configuration : IConfiguration, telemetryClient : TelemetryClient, logger : ILogger) = + inherit ControllerBase() + // Table storage : https://docs.microsoft.com/en-us/dotnet/fsharp/using-fsharp-on-azure/table-storage + let ModuleName = "Webhook-" + let tags = ["Service", "WebhookService"] + let log = Log telemetryClient + + let webhookEventNames = + let events = Microsoft.FSharp.Reflection.FSharpType.GetUnionCases(typeof) + events |> Array.map (fun e -> e.Name) + + let validateEventName (eventName:string) = + let foundEventName = + webhookEventNames + |> Array.filter(fun name -> name.ToLowerInvariant() = eventName.ToLowerInvariant()) + + if foundEventName.Length = 0 then + raiseApiError { Error = { Code = ApiErrorCode.ParseError + Message = sprintf "The event '%s' failed to parse" eventName + Target = "parseEvent" + Details = [||] + InnerError = {Message = "Verify that the webhook event is an allowed event value."} + }} + else + foundEventName.[0] + + let getCredentials () = + let applicationId = getSetting configuration "RAFT_SERVICE_PRINCIPAL_CLIENT_ID" + let clientSecret = getSetting configuration "RAFT_SERVICE_PRINCIPAL_CLIENT_SECRET" + let tenantId = getSetting configuration "RAFT_SERVICE_PRINCIPAL_TENANT_ID" + + Authentication.AzureCredentialsFactory() + .FromServicePrincipal( + applicationId, + clientSecret, + tenantId, AzureEnvironment.AzureGlobalCloud) + + let createTopic (gridClient : EventGridManagementClient) (topicName : string) = + async { + //event grid error + if topicName.Length < 3 || topicName.Length > 128 then + raiseApiError { Error = { Code = ApiErrorCode.ParseError + Message = sprintf "DomainTopic name must be between 3 and 128 characters in length." + Target = "createTopic" + Details = [||] + InnerError = {Message = ""} + }} + + let resourceGroup = getSetting configuration "RAFT_RESOURCE_GROUP_NAME" + let eventDomain = getSetting configuration "RAFT_EVENT_DOMAIN" + try + return! gridClient.DomainTopics.GetAsync(resourceGroup, eventDomain, topicName) |> Async.AwaitTask + with ex -> + return! gridClient.DomainTopics.CreateOrUpdateAsync(resourceGroup, eventDomain, topicName) |> Async.AwaitTask + } + + let createSubscription (gridClient : EventGridManagementClient) topicId targetUrl (event : string) = + async { + let destination = Models.WebHookEventSubscriptionDestination(targetUrl.ToString()) + let filter = Models.EventSubscriptionFilter(event) + let subscription = Models.EventSubscription(event, event, "", topicId , "", destination, filter) + let eventSubscriptionScope = topicId + return! gridClient.EventSubscriptions.CreateOrUpdateAsync(eventSubscriptionScope, event, subscription) + |> Async.AwaitTask + } + + let createGridClient () = + let subscriptionId = getSetting configuration "RAFT_SERVICE_PRINCIPAL_SUBSCRIPTION_ID" + let gridClient = new EventGridManagementClient(getCredentials ()) + gridClient.SubscriptionId <- subscriptionId + gridClient + + let tryGetSubscriptions (gridClient : EventGridManagementClient) topic = + try + let resourceGroup = getSetting configuration "RAFT_RESOURCE_GROUP_NAME" + let eventDomain = getSetting configuration "RAFT_EVENT_DOMAIN" + + let webhooks = gridClient.EventSubscriptions.ListByDomainTopic(resourceGroup, eventDomain, topic) + |> Seq.map(fun (sub) -> let wh = sub.Destination :?> Models.WebHookEventSubscriptionDestination + { + WebhookName = topic.ToLowerInvariant() + Event = sub.Filter.SubjectBeginsWith + TargetUrl = Uri(wh.EndpointBaseUrl) + }) + Some(webhooks) + with ex -> + raiseApiError { Error = { Code = ApiErrorCode.InvalidTag + Message = ex.ToString() + Target = "" + Details = [||] + InnerError = {Message = "The webhook tag must be an existing value."} + }} + + // https://docs.microsoft.com/en-us/rest/api/eventgrid/version2020-04-01-preview/eventsubscriptions/createorupdate + [] + [] + /// + /// Associates a webhook "tag" with an event and target URL + /// + /// + /// Sample response: + /// { + /// "WebhookName" : "fooTag" + /// "Event" : "BugFound" + /// "TargetUrl" : "https://mywebhookreceiver" + /// } + /// + /// A WebHook data type + /// Returns success. + /// Returns bad request if an exception occurs. The exception text will give the reason for the failure. + member this.Put([] webhookRequest:WebHook) = + task { + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + + // Externally we use the term SubscriptionName, this equates to a topic name in + // the event grid model. Topics have subscriptions. The subscription will be named the name of the event. + let method = ModuleName + "Put" + let tags = tags @ ["Method", method] + + try + // By using we need to: + // Need to validate that the fields are not null + if String.IsNullOrWhiteSpace webhookRequest.WebhookName + || String.IsNullOrWhiteSpace webhookRequest.Event + || String.IsNullOrWhiteSpace (webhookRequest.TargetUrl.ToString()) then + raiseApiError { Error = { Code = ApiErrorCode.ParseError + Message = "Fields cannot be null" + Target = "PUT" + Details = [||] + InnerError = {Message = "Verify you are using the correct data structure and values."} + }} + + // Need to validate that the URL is a URL. + let targetParseResult, url = Uri.TryCreate(webhookRequest.TargetUrl.ToString(), UriKind.Absolute) + if targetParseResult = false then + raiseApiError { Error = { Code = ApiErrorCode.ParseError + Message = "TargetUrl must be a proper Url." + Target = "PUT" + Details = [||] + InnerError = {Message = "Verify you are using the correct data structure and values."} + }} + + log.Info "Creating webhook" (tags@["name", webhookRequest.WebhookName; "event", webhookRequest.Event]) + + // Validates that the event name a legitimate value we support. + let requestedEvent = validateEventName webhookRequest.Event + let webhookName = webhookRequest.WebhookName.ToLowerInvariant() + let targetUrl = webhookRequest.TargetUrl.ToString() + + let gridClient = createGridClient() + let! topic = createTopic gridClient webhookName + log.Info "Creating topic" (tags@["name", webhookRequest.WebhookName; "event", webhookRequest.Event]) + let! _ = createSubscription gridClient topic.Id targetUrl (requestedEvent.ToString()) + + let hook = { + WebhookName = topic.Name + Event = requestedEvent.ToString() + TargetUrl = webhookRequest.TargetUrl + } + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + return JsonResult(hook) + + with + | Errors.ApiErrorException (apiError) as ex-> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + log.Exception ex tags + return setApiErrorStatusCode apiError Microsoft.AspNetCore.Http.StatusCodes.Status400BadRequest + } + + [] + /// + /// List the webhooks associated with the tag. Optionally provide an event in the query string to just show that one event. + /// + /// + /// Sample response: + /// { + /// "WebhookName" : "fooTag" + /// "Event" : "BugFound" + /// "TargetUrl" : "https://mywebhookreceiver" + /// } + /// + /// Name of the webhook "tag" + /// Optional query string identifying the event + /// Returns success. + /// If the webhook tag is not found + /// If the event name in the query string is not a supported value + member this.List ([] name:string, []event:string) = + task { + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + + let method = ModuleName + "List" + let tags = tags @ ["Method", method] + + try + if String.IsNullOrWhiteSpace name then + raiseApiError { Error = { Code = ApiErrorCode.QueryStringMissing + Message = "Missing required query string" + Target = method + Details = [||] + InnerError = {Message = "name"} + }} + + + // validate the eventName + let gridClient = createGridClient() + let subsOption = tryGetSubscriptions gridClient (name.ToLowerInvariant()) + match subsOption with + | Some subs -> + if isNull event then + return JsonResult(subs) + else + let eventFilter = validateEventName event + let sub = subs |> Seq.filter(fun s -> s.Event.ToString().ToLowerInvariant() = eventFilter.ToString().ToLowerInvariant()) + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + return JsonResult(sub) + + | None -> return raiseApiError { Error = + { Code = ApiErrorCode.NotFound + Message = "No subscriptions found" + Target = method + Details = [||] + InnerError = {Message = ""} + }} + + with + | Errors.ApiErrorException (apiError) as ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + log.Exception ex tags + match apiError.Error.Code with + | ApiErrorCode.NotFound -> + return setApiErrorStatusCode apiError Microsoft.AspNetCore.Http.StatusCodes.Status404NotFound + | _ -> + return setApiErrorStatusCode apiError Microsoft.AspNetCore.Http.StatusCodes.Status400BadRequest + } + + // Return an array of names. + [] + /// + /// List all the supported event names. + /// + member this.ListEvents () = + task { + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + + let method = ModuleName + "ListEvents" + + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + return JsonResult(webhookEventNames) + } + + [] + /// + /// Delete the webhook for a specific event + /// + /// + /// If the name or event are not found, no error is returned. + /// + /// Name of the webhook tag + /// Name of the event + /// Returns success. + /// If the event name is not a supported value. + member this.Delete (webhookName : string, eventName : string) = + task { + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + + let method = ModuleName + "Delete" + let tags = tags @ ["Method", method] + + try + if String.IsNullOrWhiteSpace webhookName then + raiseApiError { Error = { Code = ApiErrorCode.ParseError + Message = "WebhookName cannot be empty" + Target = "DELETE" + Details = [||] + InnerError = {Message = "Verify you are using the correct data structure and values."} + }} + + let resourceGroup = getSetting configuration "RAFT_RESOURCE_GROUP_NAME" + let eventDomain = getSetting configuration "RAFT_EVENT_DOMAIN" + let gridClient = createGridClient() + let requestedEvent = validateEventName eventName + let topicOption = + try + Some(gridClient.DomainTopics.Get(resourceGroup, eventDomain, webhookName.ToLowerInvariant())) + with ex -> + None + + match topicOption with + | Some topic -> gridClient.EventSubscriptions.Delete(topic.Id, requestedEvent.ToString()) + | None -> () + + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + return JsonResult("") + with + | Errors.ApiErrorException (apiError) as ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + log.Exception ex tags + return setApiErrorStatusCode apiError Microsoft.AspNetCore.Http.StatusCodes.Status400BadRequest + } + [] + member this.TestWebHook (webhookName : string, eventName : string) = + task { + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + + let method = ModuleName + "TestWebHook" + let webhookQueue = Raft.Message.ServiceBus.Topic.events + try + if String.IsNullOrWhiteSpace webhookName then + raiseApiError { Error = { Code = ApiErrorCode.ParseError + Message = "WebhookName cannot be empty." + Target = "TestWebHook" + Details = [||] + InnerError = {Message = "Verify you are using the correct values."} + }} + + let _ = validateEventName eventName + let jobId = sprintf "webhook-test-job-status-%O" (Guid.NewGuid().ToString()) + log.Info "Testing Webhook" ["name", webhookName; "event", eventName; "jobId", sprintf "%A" jobId] + if eventName.ToLowerInvariant() = Raft.JobEvents.JobStatus.EventType.ToLowerInvariant() then + + let status : JobStatus = { + AgentName = "1" + Tool = "RESTler" + JobId = jobId + State = JobState.Running + Metrics = None + UtcEventTime = DateTime.UtcNow + Details = Some (seq [method]) + Metadata = None + } + log.Info "Setting JobStatus webhook in webhooks table" ["name", webhookName; "event", eventName; "jobId", sprintf "%A" jobId] + let entity = Raft.StorageEntities.JobWebhookEntity(jobId, webhookName) :> TableEntity + match! Utilities.raftStorage.InsertEntity Raft.StorageEntities.JobWebHookTableName entity with + | Result.Ok() -> + log.Info "Sending JobStatus test webhook" ["name", webhookName; "event", eventName; "jobId", sprintf "%A" jobId] + do! sendJobEvent webhookQueue jobId (Message.RaftEvent.createJobEvent status) + + | Result.Error (statusCode) -> + log.Error "Failed to set JobStatus webhook in Webhooks table" ["httpErrorCode", sprintf "%A" statusCode; "webhookName", webhookName; "event", eventName; "jobId", sprintf "%A" jobId] + raiseApiError + { + Error = + { + Code = ApiErrorCode.InternalError + Message = "Failed to set JobStatus test webhook" + Target = method + Details = [||] + InnerError = {Message = ""} + } + } + + else if eventName.ToLowerInvariant() = Raft.JobEvents.BugFound<_>.EventType.ToLowerInvariant() then + let jobId = sprintf "webhook-test-bug-found-%O" (Guid.NewGuid()) + let bugFound = + { + Tool = "RESTler" + JobId = jobId + AgentName = "1" + Metadata = None + BugDetails = + { + Experiment = "experiment23" + BugBucket = "main_driver_500_1.txt" + } + } + log.Info "Setting JobStatus webhook in webhooks table" ["name", webhookName; "event", eventName; "jobId", sprintf "%A" jobId] + let entity = Raft.StorageEntities.JobWebhookEntity(jobId, webhookName) :> TableEntity + match! Utilities.raftStorage.InsertEntity Raft.StorageEntities.JobWebHookTableName entity with + | Result.Ok() -> + log.Info "Sending BugFound test webhook" ["webhookName", webhookName; "event", eventName; "jobId", sprintf "%A" jobId] + do! sendJobEvent webhookQueue jobId (Message.RaftEvent.createJobEvent bugFound) + + | Result.Error (statusCode) -> + log.Error "Failed to set BugFound webhook in Webhooks table" ["httpErrorCode", sprintf "%A" statusCode; "webhookName", webhookName; "event", eventName; "jobId", sprintf "%A" jobId] + raiseApiError + { + Error = + { + Code = ApiErrorCode.InternalError + Message = "Failed to set BugFound test webhook" + Target = method + Details = [||] + InnerError = {Message = ""} + } + } + + else + log.Error "No matching test webhook found" ["webhookName", webhookName; "event", eventName; "jobId", sprintf "%A" jobId] + raiseApiError + { + Error = + { + Code = ApiErrorCode.NotFound + Message = "The event was not found" + Target = method + Details = [||] + InnerError = {Message = ""} + } + } + stopWatch.Stop() + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest(method, float stopWatch.ElapsedMilliseconds), "milliseconds", this :> ControllerBase) + return JsonResult({ Event = eventName + Status = "Sent"}) + with + | Errors.ApiErrorException (apiError) as ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + return setApiErrorStatusCode apiError Microsoft.AspNetCore.Http.StatusCodes.Status400BadRequest + + } diff --git a/src/APIService/ApiService/DTOs.fs b/src/APIService/ApiService/DTOs.fs new file mode 100644 index 0000000..d18424f --- /dev/null +++ b/src/APIService/ApiService/DTOs.fs @@ -0,0 +1,300 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft.Controllers + +//https://docs.microsoft.com/en-us/dotnet/csharp/codedoc +module DTOs = + open System + open System.Collections.Generic + open System.ComponentModel.DataAnnotations + + /// + /// Method of authenticating with the service under test + /// + [] + type AuthenticationMethod = + { + /// + /// KeyVault Secret name containing MSAL authentication information in following format: + /// { "tenant" : "<tenantId>", "client" : "<clientid>", "secret" : "<secret>"} + /// optional values that could be passed as part of the JSON: scopes and authorityUri + /// + MSAL: string + + /// + /// Command line to execute that acquires authorization token and prints it to standard output + /// + CommandLine: string + + /// + /// KeyVault Secret name containing plain text token + /// + TxtToken: string + } + + [] + type SwaggerLocation = + { + URL: string + FilePath: string + } + + /// + /// RAFT task to run. + /// + [] + type RaftTask = + { + /// + /// Tool defined by folder name located in cli/raft-utils/tools/{ToolName} + /// + [] + ToolName: string + + /// + /// Output folder name to store agent generated output + /// Must not contain: /\*?:|<>" + /// + [] + OutputFolder : string + + /// + /// Override swagger specification location + /// + SwaggerLocation : SwaggerLocation + + /// + /// Override the Host for each request. + /// + Host : string + + /// + /// If true - do not run the task. Idle container to allow user to connect to it. + /// + IsIdling: bool + + /// + /// Duration of the task; if not set, then job level duration is used. + /// For RESTler jobs - time limit is only useful for Fuzz task + /// + Duration: Nullable + + /// + /// Authentication method configuration + /// + AuthenticationMethod: AuthenticationMethod + + /// + /// List of names of secrets in Keyvault used in configuring + /// authentication credentials + /// Key Vault secret name must start with alphabetic character and + /// followed by a string of alphanumeric characters (for example 'MyName123'). + /// Secret name can be upto 127 characters long + /// + KeyVaultSecrets : string array + + ToolConfiguration : Newtonsoft.Json.Linq.JObject + } + /// + /// Mount file share from RAFT storage account to container running a payload. + /// + [] + type FileShareMount = + { + /// + /// Any fileShare name from the RAFT storage account + /// + FileShareName : string + + /// + /// Directory name under which file share is mounted on the container. For example "/my-job-config" + /// + MountPath : string + } + + + /// + /// Hardware resources to allocate for the job + /// + [] + type Resources = + { + /// + /// Number of cores to allocate for the job. + /// Default is 1 core. + /// see: https://docs.microsoft.com/en-us/azure/container-instances/container-instances-region-availability + /// + Cores : int + + /// + /// Memory to allocate for the job + /// Default is 1 GB. + /// see: https://docs.microsoft.com/en-us/azure/container-instances/container-instances-region-availability + /// + MemoryGBs : int + } + + /// + /// Webhook definition + /// + [] + type Webhook = + { + /// + /// Webhook name to associate with the job + /// + Name : string + + /// + /// Arbitrary key/value pairs that will be returned in webhooks + /// + Metadata : Dictionary + } + + /// + /// RAFT job run definition + /// + [] + type JobDefinition = + { + /// + /// Swagger specification location for the job run + /// + [] + SwaggerLocation : SwaggerLocation + + /// + /// String used as a prefix added to service generated job ID. + /// Prefix can contain only lowercase letters, numbers, and hyphens, and must begin with a letter or a number. + /// Prefix cannot contain two consecutive hyphens. + /// Can be up to 27 characters long + /// + NamePrefix : string + + /// + /// Hardware resources to allocate for the job + /// + Resources : Resources + + /// + /// RAFT Task definitions + /// + Tasks : RaftTask array + + /// + /// Duration of the job; if not set, then job runs till completion (or forever). + /// For RESTler jobs - time limit is only useful for Fuzz task + /// + Duration: Nullable + + /// + /// Override the Host for each request. + /// + Host : string + + /// + /// Webhook to trigger when running this job + /// + Webhook : Webhook + + /// + /// If set, then place all job run results into this file share + /// + RootFileShare : string + + /// + /// File shares to mount from RAFT deployment storage account as read-only directories. + /// + ReadOnlyFileShareMounts : FileShareMount array + + /// + /// File shares to mount from RAFT deployment storage account as read-write directories. + /// + ReadWriteFileShareMounts : FileShareMount array + } + + [] + type CreateJobRequest = + { + JobId : string + + JobDefinition: JobDefinition + + IsIdlingRun : bool + + Region : string + } + + + type DeleteJobRequest() = + member val JobId : string = null with get, set + + + // We need some way of designating that these types are returned to the customer + // public? external? ReturnedJobId? + // We have types we consume and types we return to the customer. What is the best + // naming convention? + type CreateJobResponse() = + member val JobId : string = null with get, set + + type JobState = + | Creating = 0 + | Created = 1 + | Running = 2 + | Completed = 3 + | ManuallyStopped = 4 + | Error = 5 + | TimedOut = 6 + + let JobStateFromInternal (s : Raft.JobEvents.JobState) = + match s with + | Raft.JobEvents.JobState.Creating -> JobState.Creating + | Raft.JobEvents.JobState.Created -> JobState.Created + | Raft.JobEvents.JobState.Running -> JobState.Running + | Raft.JobEvents.JobState.Completed -> JobState.Completed + | Raft.JobEvents.JobState.ManuallyStopped -> JobState.ManuallyStopped + | Raft.JobEvents.JobState.Error -> JobState.Error + | Raft.JobEvents.JobState.TimedOut -> JobState.TimedOut + + type RunSummary() = + member val TotalRequestCount : int = 0 with get, set + member val ResponseCodeCounts : Dictionary = Dictionary() with get, set + member val TotalBugBucketsCount : int = 0 with get, set + + static member FromInternal (s: Raft.JobEvents.RunSummary) = + RunSummary( + TotalRequestCount = s.TotalRequestCount, + ResponseCodeCounts = Dictionary(s.ResponseCodeCounts), + TotalBugBucketsCount = s.TotalBugBucketsCount) + + type JobStatus () = + member val Tool : string = "NotSet" with get, set + + member val JobId : string = null with get, set + + member val State : JobState = JobState.Creating with get, set + + member val Metrics : RunSummary = Unchecked.defaultof<_> with get, set + + member val UtcEventTime : DateTime = DateTime.MinValue with get, set + + member val Details : (string array) = [||] with get, set + + member val AgentName : string = null with get, set + + static member FromInternal (j : Raft.JobEvents.JobStatus) = + JobStatus ( + Tool = j.Tool, + + JobId = j.JobId, + State = JobStateFromInternal j.State, + Metrics = ( + match j.Metrics with + | None -> Unchecked.defaultof<_> + | Some m -> RunSummary.FromInternal m), + + UtcEventTime = j.UtcEventTime, + Details = (match j.Details with Some d -> (d |> Seq.toArray) | None -> [||]), + AgentName = j.AgentName + ) diff --git a/src/APIService/ApiService/Dockerfile b/src/APIService/ApiService/Dockerfile new file mode 100644 index 0000000..f569ca3 --- /dev/null +++ b/src/APIService/ApiService/Dockerfile @@ -0,0 +1,5 @@ +FROM mcr.microsoft.com/dotnet/core/runtime-deps:3.1-alpine +COPY . /raft/apiservice +RUN ls -al /raft/apiservice +RUN chmod +x /raft/apiservice/apiservice +CMD ["/raft/apiservice/apiservice"] \ No newline at end of file diff --git a/src/APIService/ApiService/ErrorHandling.fs b/src/APIService/ApiService/ErrorHandling.fs new file mode 100644 index 0000000..14a5bf0 --- /dev/null +++ b/src/APIService/ApiService/ErrorHandling.fs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft + +open Microsoft.AspNetCore.Http +open Microsoft.AspNetCore.Diagnostics +open Raft.Errors +open System.Net +open Raft.Telemetry + +module ErrorHandling = + let inline someExceptionOfType< ^t when ^t :> System.Exception> (e:System.Exception) = + match e with + | :? 't as ex -> Some ex + | _ -> None + + let handleExceptions (context:HttpContext) = + let settings = Newtonsoft.Json.JsonSerializerSettings() + settings.ContractResolver <- new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() + settings.Converters.Add(Newtonsoft.Json.Converters.StringEnumConverter()) + settings.Converters.Add(Microsoft.FSharpLu.Json.CompactUnionJsonConverter()) + settings.Formatting <- Newtonsoft.Json.Formatting.Indented + settings.NullValueHandling <- Newtonsoft.Json.NullValueHandling.Ignore + settings.DateTimeZoneHandling <- Newtonsoft.Json.DateTimeZoneHandling.Utc + let serialize data = Newtonsoft.Json.JsonConvert.SerializeObject(data, settings) + + let exceptionHandlerFeature = context.Features.Get() + if not <| isNull exceptionHandlerFeature then + Central.Telemetry.TrackError (TelemetryValues.Exception exceptionHandlerFeature.Error) + match exceptionHandlerFeature.Error with + | ApiErrorException apiError -> + context.Response.ContentType <- "application/json" + context.Response.StatusCode <- int HttpStatusCode.InternalServerError + context.Response.WriteAsync(serialize apiError) + + | ex -> + let apiError = + { + ApiError.Error = + { + Code = ApiErrorCode.InternalError + Message = sprintf "Internal Server Error." + Target = "" + Details = [||] + InnerError = {Message = sprintf "%s" ex.Message} + } + } + context.Response.ContentType <- "application/json" + context.Response.StatusCode <- int HttpStatusCode.InternalServerError + context.Response.WriteAsync(serialize apiError) + else + System.Threading.Tasks.Task.FromResult(0) :> System.Threading.Tasks.Task \ No newline at end of file diff --git a/src/APIService/ApiService/Interfaces.fs b/src/APIService/ApiService/Interfaces.fs new file mode 100644 index 0000000..32086e7 --- /dev/null +++ b/src/APIService/ApiService/Interfaces.fs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft +open System +open Raft.StorageEntities +open Microsoft.Azure.Cosmos.Table +open System.Threading.Tasks + +module Interfaces = + + type IRaftStorage = + abstract member IsSuccessCode : int -> bool + abstract member CreateTable : string -> Async + abstract member GetTable : string -> Async + abstract member GetJobStatusEntities : TableQuery -> Task> + abstract member TableEntryExists : string -> string -> string -> Task> + abstract member InsertEntity : string -> TableEntity -> Task> diff --git a/src/APIService/ApiService/Program.fs b/src/APIService/ApiService/Program.fs new file mode 100644 index 0000000..0889d97 --- /dev/null +++ b/src/APIService/ApiService/Program.fs @@ -0,0 +1,253 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Learn more about F# at http://fsharp.org +namespace Raft.Main + +open Microsoft.AspNetCore.Builder +open Microsoft.AspNetCore.Hosting +open Microsoft.Extensions.DependencyInjection +open Microsoft.Extensions.Logging +open Microsoft.Extensions.Configuration +open System.IO +open System.Reflection +open Raft.Telemetry +open Raft +open Microsoft.AspNetCore.Cors.Infrastructure +open Microsoft.AspNetCore +open Microsoft.ApplicationInsights +open Microsoft.ApplicationInsights.Extensibility +open Raft.Message +open Microsoft.Azure +open System +open Microsoft.Azure.ServiceBus.Core +open Microsoft.AspNetCore.Mvc +open Microsoft.OpenApi.Models +open Microsoft.AspNetCore.Http +open Microsoft.AspNetCore.Authentication.AzureAD.UI +open Microsoft.AspNetCore.Authentication +open Swashbuckle.AspNetCore.SwaggerGen + +module main = + + let loadSchemaDocuments() = + async { + let utilsFileShare = Environment.GetEnvironmentVariable("RAFT_UTILS_FILESHARE") + let utilsSas = Environment.GetEnvironmentVariable("RAFT_UTILS_SAS") + + let directoryClient = Azure.Storage.Files.Shares.ShareDirectoryClient(utilsSas, utilsFileShare, "tools") + + let asyncEnum = directoryClient.GetFilesAndDirectoriesAsync().GetAsyncEnumerator() + + let rec loadAllConfigs(allConfigs) = + async { + let! next = asyncEnum.MoveNextAsync().AsTask() |> Async.AwaitTask + if next then + if asyncEnum.Current.IsDirectory then + try + let fileClient = directoryClient.GetSubdirectoryClient(asyncEnum.Current.Name).GetFileClient("schema.json") + let! fileExists = fileClient.ExistsAsync() |> Async.AwaitTask + if fileExists.Value then + let! fileStream = fileClient.DownloadAsync() |> Async.AwaitTask + use r = new System.IO.StreamReader(fileStream.Value.Content) + let! file = r.ReadToEndAsync() |> Async.AwaitTask + return! loadAllConfigs (Map.add asyncEnum.Current.Name (Some file) allConfigs) + else + return! loadAllConfigs (Map.add asyncEnum.Current.Name None allConfigs) + with ex -> + Central.Telemetry.TrackError(TelemetryValues.Exception(ex)) + return! loadAllConfigs (Map.add asyncEnum.Current.Name None allConfigs) + else + return! loadAllConfigs allConfigs + else + return allConfigs + } + return! loadAllConfigs Map.empty + } + + let getSchemaDocuments () = + async { + let! schemaEntities = loadSchemaDocuments() + return schemaEntities + |> Map.map (fun tool schema -> + let reader = Microsoft.OpenApi.Readers.OpenApiStringReader() + let schemaDocument = + match schema with + | None -> + let noSchemaToolDoc = OpenApiDocument(Components = OpenApiComponents()) + let noSchemaToolSchema = OpenApiSchema(Title = tool) + noSchemaToolDoc.Components.Schemas.Add(tool, noSchemaToolSchema) + noSchemaToolDoc + | Some s -> + let schemaDoc, openApiDiagnostic = reader.Read(s) + if openApiDiagnostic.Errors.Count <> 0 then + raise <| Exception("Errors in the schema document") + schemaDoc + schemaDocument + ) + } + + type RaftSwaggerDocumentFilter() = + interface IDocumentFilter with + member this.Apply(swaggerDoc : OpenApiDocument, context : DocumentFilterContext): unit = + let schemaDocuments = getSchemaDocuments () |> Async.RunSynchronously + schemaDocuments + |> Map.iter(fun toolName schemaDocument -> + // Add all the schema references to the global schema repository if it does not already exist. + for pair in schemaDocument.Components.Schemas do + if not (context.SchemaRepository.Schemas.ContainsKey(pair.Key)) then + context.SchemaRepository.Schemas.Add(pair.Key, pair.Value) + ) + + type RaftSwaggerSchemaFilter() = + interface ISchemaFilter with + member this.Apply(schema: OpenApiSchema, context: SchemaFilterContext): unit = + if not (isNull context.MemberInfo) && + context.MemberInfo.Name = "TaskConfiguration" && + context.MemberInfo.DeclaringType.Name = "RaftTask" then + + let schemaDocuments = getSchemaDocuments () |> Async.RunSynchronously + schemaDocuments + |> Map.iter(fun toolName schemaDocument -> + for pair in schemaDocument.Components.Schemas do + // We will find the schema entry that matches the name of the tool + // This entry then is #ref referenced to the RaftTask->TaskConfiguration "anyOf" schema + if pair.Key = toolName then + schema.AnyOf.Add(pair.Value) + ) + + let configureCors (builder : CorsPolicyBuilder) = + builder.WithOrigins("http://localhost:5001") + .AllowAnyMethod() + .AllowAnyHeader() + |> ignore + + let configureApp (app : IApplicationBuilder) = + app.UseAuthentication() + .UseCors(configureCors) + .UseExceptionHandler(fun options -> options.Run(RequestDelegate ErrorHandling.handleExceptions)) + .UseMvc() + .UseSwagger() + .UseSwaggerUI(fun config -> config.SwaggerEndpoint("/swagger/v1/swagger.json", "RAFT API")) + |> ignore + + if Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") <> "Development" then + app.UseHttpsRedirection() |> ignore + + let configureServices (services : IServiceCollection) = + + let serviceProvider = services.BuildServiceProvider() + let settings = serviceProvider.GetService() + let metricsKey = settings.["RAFT_METRICS_APP_INSIGHTS_KEY"] + let siteHash = settings.["RAFT_SITE_HASH"] + settings.["RestartTime"] <- DateTimeOffset.UtcNow.ToString() + + printfn "Initializing central telemetry" + ignore <| Central.Initialize (TelemetryClient(new TelemetryConfiguration(metricsKey), InstrumentationKey = metricsKey)) siteHash + + Raft.Utilities.serviceStartTime <- System.DateTimeOffset.UtcNow + Raft.Utilities.raftStorage <- Raft.Storage.RaftStorage(settings.[Constants.StorageTableConnectionString]) + Raft.Utilities.serviceBusSenders <- Map.empty + .Add(Raft.Message.ServiceBus.Queue.create, + ServiceBus.Core.MessageSender( + settings.[Constants.ServiceBusConnectionStringSetting], + Raft.Message.ServiceBus.Queue.create, ServiceBus.RetryPolicy.Default) :> IMessageSender) + .Add(Raft.Message.ServiceBus.Queue.delete, + ServiceBus.Core.MessageSender( + settings.[Constants.ServiceBusConnectionStringSetting], + Raft.Message.ServiceBus.Queue.delete, ServiceBus.RetryPolicy.Default) :> IMessageSender) + .Add(Raft.Message.ServiceBus.Topic.events, + ServiceBus.Core.MessageSender( + settings.[Constants.ServiceBusConnectionStringSetting], + Raft.Message.ServiceBus.Topic.events, ServiceBus.RetryPolicy.Default) :> IMessageSender) + + + services.AddApplicationInsightsTelemetry() + .AddSwaggerGenNewtonsoftSupport() + .AddSwaggerGen(fun config -> + config.SwaggerDoc("v1", OpenApiInfo (Title = "RAFT", Version = "v1")) + config.UseOneOfForPolymorphism() + + // Set the comments path for the Swagger JSON and UI. + let xmlFile = sprintf "%s.xml" (Assembly.GetExecutingAssembly().GetName().Name) + let xmlPath = Path.Join(AppContext.BaseDirectory, xmlFile); + config.IncludeXmlComments(xmlPath) + config.SchemaFilter() + config.DocumentFilter() + ) + .AddCors() + .AddMvc(fun options -> options.EnableEndpointRouting <- false) + .SetCompatibilityVersion(CompatibilityVersion.Latest) + |> ignore + + services.AddControllers().AddJsonOptions(fun options -> + options.JsonSerializerOptions.Converters.Add(Text.Json.Serialization.JsonStringEnumConverter(System.Text.Json.JsonNamingPolicy.CamelCase)) + ) + .AddNewtonsoftJson(fun options -> + options.SerializerSettings.Converters.Add(Newtonsoft.Json.Converters.StringEnumConverter()) + + options.SerializerSettings.Formatting <- Newtonsoft.Json.Formatting.Indented + options.SerializerSettings.NullValueHandling <- Newtonsoft.Json.NullValueHandling.Ignore + options.SerializerSettings.DateTimeZoneHandling <- Newtonsoft.Json.DateTimeZoneHandling.Utc + options.SerializerSettings.ContractResolver <- Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() + options.SerializerSettings.TypeNameHandling <- Newtonsoft.Json.TypeNameHandling.Auto + ) + |> ignore + + // Enable logging of details on console window + Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII <- true + + services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme) + .AddAzureADBearer(fun options -> options.ClientId <- settings.["RAFT_SERVICE_PRINCIPAL_CLIENT_ID"] + options.Instance <- "https://login.microsoftonline.com/" + options.TenantId <- settings.["RAFT_SERVICE_PRINCIPAL_TENANT_ID"] + ) + //https://developer.okta.com/blog/2018/03/23/token-authentication-aspnetcore-complete-guide + .AddJwtBearer(fun options -> + // It is important to validate the audience so we know this token is for us. + options.TokenValidationParameters.ValidAudience <- settings.["RAFT_SERVICE_PRINCIPAL_CLIENT_ID"] + options.TokenValidationParameters.ValidateAudience <- true + + options.TokenValidationParameters.ValidateLifetime <- true + options.TokenValidationParameters.ValidateIssuerSigningKey <- true + + options.TokenValidationParameters.ClockSkew <- TimeSpan.FromMinutes(5.0) + ) + |> ignore + + // Pre-create the tables once when startup up so the running controllers does not need to. + // This eliminates a bunch of 409's. + do Raft.Utilities.raftStorage.CreateTable Raft.StorageEntities.JobWebHookTableName |> Async.RunSynchronously |> ignore + do Raft.Utilities.raftStorage.CreateTable Raft.StorageEntities.JobStatusTableName |> Async.RunSynchronously |> ignore + do Raft.Utilities.raftStorage.CreateTable Raft.StorageEntities.JobTableName |> Async.RunSynchronously |> ignore + + let configureLogging (builder : ILoggingBuilder) = + builder.AddConsole() // Set up the Console logger + .AddDebug() // Set up the Debug logger + .AddApplicationInsights() + |> ignore + + let configureAppConfiguration(context: WebHostBuilderContext) (config: IConfigurationBuilder) = + + config + .SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)) + .AddJsonFile("appsettings.json", false, true) + // When running locally, don't forget to add the appsettings.Development.json file and set the + // property to always copy. + .AddJsonFile(sprintf "appsettings.%s.json" context.HostingEnvironment.EnvironmentName, true) + .AddEnvironmentVariables() |> ignore + + [] + let main argv = + + WebHost + .CreateDefaultBuilder() + .Configure(Action configureApp) + .ConfigureAppConfiguration(configureAppConfiguration) + .ConfigureServices(configureServices) + .ConfigureLogging(configureLogging) + .UseUrls(sprintf "http://*:%s" (Environment.GetEnvironmentVariable("PORT"))) + .Build() + .Run() + + 0 diff --git a/src/APIService/ApiService/Storage.fs b/src/APIService/ApiService/Storage.fs new file mode 100644 index 0000000..ab9d671 --- /dev/null +++ b/src/APIService/ApiService/Storage.fs @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft + +open System +open Raft.StorageEntities +open Microsoft.AspNetCore.Http +open Raft.Controllers +open Microsoft.Azure.Cosmos.Table +open Raft.Interfaces +open FSharp.Control.Tasks.V2.ContextSensitive +open Microsoft.Extensions.Logging + +module Storage = + type RaftStorage (connectionString : string) = + interface IRaftStorage with + member this.IsSuccessCode statusCode = + statusCode >= 200 && statusCode <= 299 + + member this.GetTable tableName = + async { + let storageAccount = CloudStorageAccount.Parse(connectionString) + let tableClient = storageAccount.CreateCloudTableClient() + let table = tableClient.GetTableReference(tableName) + return table + } + + member this.CreateTable tableName = + async { + let storageAccount = CloudStorageAccount.Parse(connectionString) + let tableClient = storageAccount.CreateCloudTableClient() + let table = tableClient.GetTableReference(tableName) + let! createResult = table.CreateIfNotExistsAsync() |> Async.AwaitTask + return table + } + + member this.GetJobStatusEntities (query : TableQuery) = + task { + let me = this :> IRaftStorage + let! table = me.GetTable StorageEntities.JobStatusTableName + //https://github.com/rspeele/TaskBuilder.fs + // TODO: Remove tail recursion use of the task + // See github readme + + let rec doExecute (token: TableContinuationToken) (results: JobStatusEntity seq) = + task { + let! segment = table.ExecuteQuerySegmentedAsync(query, token) + + if segment.ContinuationToken = null then + return Seq.append results segment.Results + else + return! doExecute segment.ContinuationToken (Seq.append results segment.Results) + } + return! doExecute null [] + } + + member this.TableEntryExists tableName partitionKey rowKey = + task{ + let me = this :> IRaftStorage + let! table = me.GetTable tableName + let getOp = Microsoft.Azure.Cosmos.Table.TableOperation.Retrieve(partitionKey, rowKey) + let! getResult = table.ExecuteAsync(getOp) |> Async.AwaitTask + if (me.IsSuccessCode getResult.HttpStatusCode) then + return Result.Ok() + else + return Result.Error getResult.HttpStatusCode + + } + + member this.InsertEntity tableName entity = + task { + let me = this :> IRaftStorage + let! table = me.GetTable tableName + let insertOperation = TableOperation.Insert(entity) + let! insertOperationResult = table.ExecuteAsync(insertOperation) |> Async.AwaitTask + if me.IsSuccessCode insertOperationResult.HttpStatusCode then + return Result.Ok() + else + return Result.Error insertOperationResult.HttpStatusCode + } + diff --git a/src/APIService/ApiService/TelemetryApiService.fs b/src/APIService/ApiService/TelemetryApiService.fs new file mode 100644 index 0000000..f610249 --- /dev/null +++ b/src/APIService/ApiService/TelemetryApiService.fs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft.Telemetry + +open System.Diagnostics +open Microsoft.AspNetCore.Mvc +open System.Reflection +open Microsoft.ApplicationInsights.Metrics + +module TelemetryApiService = + type Raft.Telemetry.Central.TelemetryImpl with + member this.TrackMetric (telemetryValue:TelemetryValues, units, controller : ControllerBase) = + // The telemetry client value can be null during unit testing. We don't want to pollute the + // our metrics with unit tests. + let version = Assembly.GetEntryAssembly().GetName().Version + match this.TelemetryConfig with + | Some (telemetry, site) -> + match telemetryValue with + | ApiRequest (methodName, duration) -> + let m = telemetry.GetMetric(MetricIdentifier("ApiRequest", methodName, "Units", "SiteHash", "ResponseCode", "Version")) + + m.TrackValue(duration, units, site, controller.Response.StatusCode.ToString(), version.ToString()) |> ignore + | v -> this.TrackMetric(v, units) + | None -> () \ No newline at end of file diff --git a/src/APIService/ApiService/Utilities.fs b/src/APIService/ApiService/Utilities.fs new file mode 100644 index 0000000..a06e9de --- /dev/null +++ b/src/APIService/ApiService/Utilities.fs @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft + +open Microsoft.AspNetCore.Http +open Message +open Microsoft.Extensions.Configuration +open Raft.Errors +open Microsoft.Azure.ServiceBus.Core +open Microsoft.Azure +open Interfaces +open System +open Storage +open Microsoft.AspNetCore.Mvc + +module Utilities = + let mutable serviceStartTime = System.DateTimeOffset.MinValue + let mutable serviceBusSenders : Map = Map.empty + let mutable raftStorage : IRaftStorage = RaftStorage("") :> IRaftStorage + + let tryGetQueryStringValue (request:HttpRequest) (key:string) = + request.Query + |> Seq.tryFind (fun (keyValue) -> System.String.Compare(keyValue.Key, key, StringComparison.InvariantCultureIgnoreCase) = 0) + |> Option.map (fun pair -> pair.Value.[0]) + + let getSetting (settings : IConfiguration) (name:string) = + let value = settings.GetValue(name, System.String.Empty).ToString() + if value = System.String.Empty then + raiseApiError + { Error = { Code = ApiErrorCode.QueryStringMissing + Message = "Setting not found." + Target = "getSetting" + Details = [||] + InnerError = {Message = name } + }} + else + value + + let deserializeCommand (message: string) = + let decodedMessage: 'a = + let m = RaftCommand.deserializeJson message + m.Message + decodedMessage + + let sendCommand queue (sessionId: string) data = + async { + let sender = + if obj.ReferenceEquals(serviceBusSenders, null) then + // This should never happen. + failwith "ServiceBus sender object not set" + else + serviceBusSenders.[queue] + + let message = ServiceBus.Message(Raft.Message.RaftCommand.serializeToBytes data, SessionId = sessionId.ToString()) + do! sender.SendAsync(message) |> Async.AwaitTask + } + + let inline sendJobEvent queue (sessionId: string) data = + async { + let sender = + if obj.ReferenceEquals(serviceBusSenders, null) then + // This should never happen. + failwith "ServiceBus sender object not set" + else + serviceBusSenders.[queue] + + let message = ServiceBus.Message(Raft.Message.RaftEvent.serializeToBytes data, SessionId = sessionId.ToString()) + do! sender.SendAsync(message) |> Async.AwaitTask + } + + let setApiErrorStatusCode apiError code = + let result = JsonResult(apiError) + result.StatusCode <- Nullable(code) + result + + diff --git a/src/APIService/ApiService/WebhookVerbs.fs b/src/APIService/ApiService/WebhookVerbs.fs new file mode 100644 index 0000000..130dc6e --- /dev/null +++ b/src/APIService/ApiService/WebhookVerbs.fs @@ -0,0 +1,347 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft.Controllers +// +// https://docs.microsoft.com/en-us/azure/event-grid/post-to-custom-topic +// https://github.com/Azure-Samples/event-grid-dotnet-publish-consume-events/blob/master/EventGridPublisher/TopicPublisher/Program.cs + +open Giraffe +open Microsoft.AspNetCore.Http +open FSharp.Control.Tasks.V2 +open System +open Raft.Errors.ErrorHandling +open Raft.Webhooks +open Raft.Controllers.AppInsights +open Microsoft.Azure.Management.EventGrid +open Microsoft.Azure.EventGrid +open Microsoft.Azure.Management.ResourceManager.Fluent +open Microsoft.Rest.Azure +open Raft.JobStatus +open Raft.Telemetry +open Raft.Utilities +open Raft + +// Table storage : https://docs.microsoft.com/en-us/dotnet/fsharp/using-fsharp-on-azure/table-storage +module WebhookVerbs = + let ModuleName = "WebhookVerbs-" + let tags = ["Service", "WebhookService"] + + let parseEvent (eventString:string) = + let parseResult, eventRequested = Enum.TryParse (eventString.ToLower()) + if parseResult = false then + raiseApiError { Error = { Code = ApiErrorCode.ParseError + Message = sprintf "The event '%s' failed to parse" eventString + Target = "parseEvent" + Details = [||] + InnerError = {Message = "Verify that the webhook event is an allowed event value."} + }} + eventRequested + + + let getCredentials (ctx : HttpContext) = + let applicationId = getSetting ctx "RAFT_SERVICE_PRINCIPAL_CLIENT_ID" + let clientSecret = getSetting ctx "RAFT_SERVICE_PRINCIPAL_CLIENT_SECRET" + let tenantId = getSetting ctx "RAFT_SERVICE_PRINCIPAL_TENANT_ID" + + Authentication.AzureCredentialsFactory() + .FromServicePrincipal( + applicationId, + clientSecret, + tenantId, AzureEnvironment.AzureGlobalCloud) + + let createTopic ctx (gridClient : EventGridManagementClient) (topicName : string) (eventName : WebhookEvents) = + async { + let resourceGroup = getSetting ctx "RAFT_RESOURCE_GROUP_NAME" + let eventDomain = getSetting ctx "RAFT_EVENT_DOMAIN" + try + return! gridClient.DomainTopics.GetAsync(resourceGroup, eventDomain, topicName) |> Async.AwaitTask + with ex -> + return! gridClient.DomainTopics.CreateOrUpdateAsync(resourceGroup, eventDomain, topicName) |> Async.AwaitTask + } + + let createSubscription (gridClient : EventGridManagementClient) topicId targetUrl (event : string) = + async { + let destination = Models.WebHookEventSubscriptionDestination(targetUrl.ToString()) + let filter = Models.EventSubscriptionFilter(event) + let subscription = Models.EventSubscription(event, event, "", topicId , "", destination, filter) + let eventSubscriptionScope = topicId + return! gridClient.EventSubscriptions.CreateOrUpdateAsync(eventSubscriptionScope, event, subscription) + |> Async.AwaitTask + } + + let createGridClient ctx = + let subscriptionId = getSetting ctx "RAFT_SERVICE_PRINCIPAL_SUBSCRIPTION_ID" + let gridClient = new EventGridManagementClient(getCredentials ctx) + gridClient.SubscriptionId <- subscriptionId + gridClient + + let tryGetSubscription ctx (gridClient : EventGridManagementClient) subscriptionName (event:WebhookEvents) = + let resourceGroup = getSetting ctx "RAFT_RESOURCE_GROUP_NAME" + let eventDomain = getSetting ctx "RAFT_EVENT_DOMAIN" + try + let subscriptions = gridClient.EventSubscriptions.ListByDomainTopic(resourceGroup, eventDomain,subscriptionName) + let sub = subscriptions |> Seq.filter(fun s -> s.Name = event.ToString()) + match Seq.length sub with + | 1 -> Some (sub |> Seq.head) + | _ -> None + with exn -> + None + + let tryGetSubscriptions ctx (gridClient : EventGridManagementClient) topic = + try + let resourceGroup = getSetting ctx "RAFT_RESOURCE_GROUP_NAME" + let eventDomain = getSetting ctx "RAFT_EVENT_DOMAIN" + + let webhooks = gridClient.EventSubscriptions.ListByDomainTopic(resourceGroup, eventDomain, topic) + |> Seq.map(fun (sub) -> let wh = sub.Destination :?> Models.WebHookEventSubscriptionDestination + { + WebhookName = topic.ToLower() + Event = sub.Filter.SubjectBeginsWith + TargetUrl = Uri(wh.EndpointBaseUrl) + }) + Some(webhooks) + with ex -> + raiseApiError { Error = { Code = ApiErrorCode.InvalidCustomer + Message = ex.ToString() + Target = "" + Details = [||] + InnerError = {Message = "The webhook tag must be an existing value."} + }} + + // https://docs.microsoft.com/en-us/rest/api/eventgrid/version2020-04-01-preview/eventsubscriptions/createorupdate + let CreateOrUpdateWebHookSubscription : HttpHandler = + fun (next : HttpFunc) (ctx : HttpContext) -> task { + // Externally we use the term SubscriptionName, this equates to a topic name in + // the event grid model. Topics have subscriptions. The subscription will be named the name of the event. + let method = ModuleName + "CreateOrUpdateWebHookSubscription" + let log = Log ctx + let tags = tags @ ["Method", method] + + try + use reader = new System.IO.StreamReader(ctx.Request.Body) + let body = reader.ReadToEnd() + let webhookRequest = + try + Microsoft.FSharpLu.Json.Compact.deserialize(body) + with ex -> + raiseApiError { Error = { Code = ApiErrorCode.ParseError + Message = sprintf "Unable to parse %s body" ctx.Request.Method + Target = method + Details = [||] + InnerError = {Message = ex.Message} + }} + + let requestedEvent = parseEvent (webhookRequest.Event.ToLower()) + let webhookName = webhookRequest.WebhookName.ToLower() + let targetUrl = webhookRequest.TargetUrl.ToString() + + let gridClient = createGridClient ctx + let! topic = createTopic ctx gridClient webhookName requestedEvent + let! _ = createSubscription gridClient topic.Id targetUrl (requestedEvent.ToString()) + + let hook = { + WebhookName = topic.Name + Event = requestedEvent.ToString() + TargetUrl = webhookRequest.TargetUrl + } + + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest method) (Some ctx) None + return! Successful.OK hook next ctx + + with + | ApiErrorException (apiError) as ex-> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + log.Exception ex tags + return! RequestErrors.BAD_REQUEST apiError next ctx + | ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + log.Exception ex tags + return! RequestErrors.BAD_REQUEST { Error = { Code = ApiErrorCode.InternalError + Message = ex.Message + Target = method + Details = [||] + InnerError = {Message = "Unexpected error."} + }} next ctx + } + + let GetWebHooks : HttpHandler = + fun (next : HttpFunc) (ctx : HttpContext) -> task { + let method = "GetWebHooks" + let log = Log ctx + let tags = tags @ ["Method", method] + + // Query strings + // name=&event= + + try + let webhookNameOption = ctx.TryGetQueryStringValue "name" + let webhookName = + match webhookNameOption with + | Some sn -> sn + | None -> raiseApiError { Error = { Code = ApiErrorCode.QueryStringMissing + Message = "Missing required query string" + Target = method + Details = [||] + InnerError = {Message = "name"} + }} + + let eventNameOption = ctx.TryGetQueryStringValue "event" + + // validate the eventName + let gridClient = createGridClient ctx + let subsOption = tryGetSubscriptions ctx gridClient webhookName + match subsOption with + | Some subs -> + match eventNameOption with + | None -> return! Successful.OK subs next ctx + | Some name -> + let event = parseEvent name + let sub = subs |> Seq.filter(fun s -> s.Event.ToLower() = event.ToString().ToLower()) + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest method) (Some ctx) None + return! Successful.OK sub next ctx + + | None -> return raiseApiError { Error = + { Code = ApiErrorCode.NotFound + Message = "No subscriptions found" + Target = method + Details = [||] + InnerError = {Message = ""} + }} next ctx + + with + | ApiErrorException (apiError) as ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + log.Exception ex tags + return! RequestErrors.BAD_REQUEST apiError next ctx + + | ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + log.Exception ex tags + return! RequestErrors.BAD_REQUEST { Error = + { Code = ApiErrorCode.InternalError + Message = ex.Message + Target = method + Details = [||] + InnerError = {Message = "Unexpected error."} + }} next ctx + } + + // Return an array of names. + let GetWebHookEvents : HttpHandler = + fun (next : HttpFunc) (ctx : HttpContext) -> task { + let method = "GetWebHookEvents" + let allEvents = Enum.GetNames(typeof) + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest method) (Some ctx) None + return! Successful.OK allEvents next ctx + } + + let DeleteWebHook (webhookName : string) (eventName : string) : HttpHandler = + fun (next : HttpFunc) (ctx : HttpContext) -> task { + let method = "DeleteWebHook" + let log = Log ctx + let tags = tags @ ["Method", method] + + try + let event = parseEvent eventName + let resourceGroup = getSetting ctx "RAFT_RESOURCE_GROUP_NAME" + let eventDomain = getSetting ctx "RAFT_EVENT_DOMAIN" + let gridClient = createGridClient ctx + let topicOption = + try + Some(gridClient.DomainTopics.Get(resourceGroup, eventDomain, webhookName.ToLower())) + with ex -> + None + + match topicOption with + | Some topic -> gridClient.EventSubscriptions.Delete(topic.Id, event.ToString()) + | None -> () + + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest method) (Some ctx) None + return! Successful.OK "" next ctx + with + | ApiErrorException (apiError) as ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + log.Exception ex tags + return! RequestErrors.BAD_REQUEST apiError next ctx + + | ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + log.Exception ex tags + return! RequestErrors.BAD_REQUEST { Error = + { Code = ApiErrorCode.InternalError + Message = ex.Message + Target = method + Details = [||] + InnerError = {Message = "Unexpected error."} + } + } next ctx + } + + let createWebHook<'T> customerId event (date:DateTime) (data:'T) = + { + topic = customerId.ToString() + id = Guid.NewGuid().ToString() + eventType = event.ToString() + subject = event.ToString() + eventTime = date.ToString("O") + data = data + dataVersion = "1.0" + } + + let TestWebHook (webhookName : string) (eventName : string) : HttpHandler = + fun (next : HttpFunc) (ctx : HttpContext) -> task { + let method = "TestWebHook" + let webhookQueue = Raft.Message.ServiceBus.Queue.webhook + try + let event = parseEvent eventName + do! task { + match event with + | WebhookEvents.jobstatus -> + let status : JobStatus = { + agentName = "1" + tool = Some Tool.RESTler + jobId = Guid.NewGuid() + state = JobState.Running + metrics = None + utcEventTime = DateTime.UtcNow + details = [""] + webhookName = Some(webhookName) + } + do! sendMessage ctx webhookQueue { message = { + webhookName = webhookName + event = WebhookEvents.jobstatus + data = status + }} + | WebhookEvents.bugfound -> + let bugfound = { JobId = (Guid.NewGuid().ToString()) } + do! sendMessage ctx webhookQueue { message = { + webhookName = webhookName + event = WebhookEvents.bugfound + data = bugfound + }} + | _ -> raiseApiError { Error = { Code = ApiErrorCode.NotFound + Message = "The event was not found" + Target = method + Details = [||] + InnerError = {Message = ""} + }} + } + Central.Telemetry.TrackMetric (TelemetryValues.ApiRequest method) (Some ctx) None + return! Successful.OK (sprintf "Event '%O' Sent" event) next ctx + with + | ApiErrorException (apiError) as ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + return! RequestErrors.BAD_REQUEST apiError next ctx + + | ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + return! RequestErrors.BAD_REQUEST { Error = + { Code = ApiErrorCode.InternalError + Message = ex.Message + Target = method + Details = [||] + InnerError = {Message = "Unexpected error."} + } + } next ctx + } diff --git a/src/APIService/ApiService/appsettings.json b/src/APIService/ApiService/appsettings.json new file mode 100644 index 0000000..319fa73 --- /dev/null +++ b/src/APIService/ApiService/appsettings.json @@ -0,0 +1,13 @@ +{ + "Logging": { + "ApplicationInsights": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Error" + } + }, + "LogLevel": { + "Default": "Information" + } + } +} diff --git a/src/Agent/AzureAuth/Auth.fs b/src/Agent/AzureAuth/Auth.fs new file mode 100644 index 0000000..fe2b237 --- /dev/null +++ b/src/Agent/AzureAuth/Auth.fs @@ -0,0 +1,128 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +open System + +open Microsoft.Identity.Client +open Newtonsoft +open Microsoft.FSharpLu + +type AuthType = + | MSAL + | Token + +type SecretVariable = string + +type Config = + { + AuthType : AuthType option + Secret : SecretVariable option + PrependLine : string option + } + + static member Empty = + { + AuthType = None + Secret = None + PrependLine = None + } + + +let [] MSAL = "msal" +let [] Token = "token" + +let [] Secret = "--secret" +let [] PrependLine = "--prepend-line" + +let usage = + [ + sprintf "[%s | %s ]" MSAL Token + sprintf "[%s]" Secret + sprintf "[%s]" PrependLine + ] |> (fun args -> String.Join("\n", args)) + + +let parseCommandLine (argv: string array) = + if Array.length argv = 0 then + failwithf "Expected command line arguments %s" usage + + let rec parse (currentConfig: Config) (args: string list) = + match args with + | [] -> currentConfig + | Token :: rest -> + parse {currentConfig with AuthType = Some AuthType.Token} rest + | MSAL :: rest -> + parse {currentConfig with AuthType = Some AuthType.MSAL} rest + | Secret :: secret :: rest -> + parse {currentConfig with Secret = Some secret} rest + | PrependLine :: prependLine :: rest -> + parse {currentConfig with PrependLine = Some prependLine} rest + | arg :: _ -> + failwithf "Unhandled command line parameter: %s\nusage: %s" arg usage + + parse Config.Empty (Array.toList argv) + +type AppRegistration = + { + tenant : string + client : string + secret : string + scopes : string array option + authorityUri :string option + } + + +[] +let main argv = + async { + let config = parseCommandLine argv + + let loadSecretEnv(secretEnvVar) = + match System.Environment.GetEnvironmentVariable(sprintf "RAFT_%s" secretEnvVar) with + | s when String.IsNullOrEmpty s -> + match System.Environment.GetEnvironmentVariable(secretEnvVar) with + | ss when String.IsNullOrEmpty ss -> failwithf "Token secret is not set in the Environment" + | ss -> ss + | s -> s + + match config.AuthType with + | Some AuthType.Token -> + let token = + match config.Secret with + | Some secretEnvVar -> loadSecretEnv secretEnvVar + | None -> failwithf "Secret is not specified. Usage: %s" usage + + match config.PrependLine with + | Some h -> printfn "%s" h + | None -> () + printfn "Authorization: %s" token + + | Some AuthType.MSAL -> + match config.Secret with + | Some envVar -> + let auth : AppRegistration = envVar |> loadSecretEnv |> Json.Compact.deserialize + let scopes = + match auth.scopes with + | None -> [|sprintf "%s/.default" auth.client|] + | Some s -> s + + let cred = + let authBuilder = ConfidentialClientApplicationBuilder.Create(auth.client).WithClientSecret(auth.secret) + match auth.authorityUri with + | None -> + authBuilder.WithAuthority(AzureCloudInstance.AzurePublic, auth.tenant, true).Build() + | Some uri -> + authBuilder.WithAuthority(uri, auth.tenant, true).Build() + + let! r = cred.AcquireTokenForClient(scopes).ExecuteAsync() |> Async.AwaitTask + + match config.PrependLine with + | Some h -> printfn "%s" h + | None -> () + printfn "Authorization: %s" (r.CreateAuthorizationHeader()) + + | None -> failwithf "Secret is not specified. Usage: %s" usage + + | None -> failwithf "Auth type is not set. Usage: %s" usage + } |> Async.RunSynchronously + 0 // return an integer exit code diff --git a/src/Agent/AzureAuth/AzureAuth.fsproj b/src/Agent/AzureAuth/AzureAuth.fsproj new file mode 100644 index 0000000..c03a6bf --- /dev/null +++ b/src/Agent/AzureAuth/AzureAuth.fsproj @@ -0,0 +1,21 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + + + + + diff --git a/src/Agent/Dockerfile b/src/Agent/Dockerfile new file mode 100644 index 0000000..15c18b9 --- /dev/null +++ b/src/Agent/Dockerfile @@ -0,0 +1,3 @@ +FROM acrrestler.azurecr.io/restler:restlerv6.1 +COPY RestlerAgent /raft/agent +COPY RaftResultAnalyzer /raft/result-analyzer diff --git a/src/Agent/RESTlerAgent.sln b/src/Agent/RESTlerAgent.sln new file mode 100644 index 0000000..c861a6e --- /dev/null +++ b/src/Agent/RESTlerAgent.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29721.120 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "RestlerAgent", "RESTlerAgent\RestlerAgent.fsproj", "{5340C72B-9B87-4345-8DAE-1B0E9CFA285F}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "RaftResultAnalyzer", "RaftResultAnalyzer\RaftResultAnalyzer.fsproj", "{32475F74-7C03-4547-ACF2-C02B1BF6F85A}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AzureAuth", "AzureAuth\AzureAuth.fsproj", "{8A202DC0-DBEC-425C-8504-BCF3FDD1AE4B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5340C72B-9B87-4345-8DAE-1B0E9CFA285F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5340C72B-9B87-4345-8DAE-1B0E9CFA285F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5340C72B-9B87-4345-8DAE-1B0E9CFA285F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5340C72B-9B87-4345-8DAE-1B0E9CFA285F}.Release|Any CPU.Build.0 = Release|Any CPU + {32475F74-7C03-4547-ACF2-C02B1BF6F85A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32475F74-7C03-4547-ACF2-C02B1BF6F85A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32475F74-7C03-4547-ACF2-C02B1BF6F85A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32475F74-7C03-4547-ACF2-C02B1BF6F85A}.Release|Any CPU.Build.0 = Release|Any CPU + {8A202DC0-DBEC-425C-8504-BCF3FDD1AE4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A202DC0-DBEC-425C-8504-BCF3FDD1AE4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A202DC0-DBEC-425C-8504-BCF3FDD1AE4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A202DC0-DBEC-425C-8504-BCF3FDD1AE4B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F19F65F1-F41E-425D-B1DC-D425E267B007} + EndGlobalSection +EndGlobal diff --git a/src/Agent/RESTlerAgent/AgentMain.fs b/src/Agent/RESTlerAgent/AgentMain.fs new file mode 100644 index 0000000..e446b82 --- /dev/null +++ b/src/Agent/RESTlerAgent/AgentMain.fs @@ -0,0 +1,863 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +module RESTlerAgent + +open System +open Microsoft.Azure +open Raft.Message +open Newtonsoft +open Microsoft.FSharpLu +open Microsoft.ApplicationInsights +open RESTlerAgentConfigTypes + +let inline (++) (path1: string) (path2 : string) = IO.Path.Join(path1, path2) + +type System.Threading.Tasks.Task with + member x.ToAsync = Async.AwaitTask(x) + +type System.Threading.Tasks.Task<'T> with + member x.ToAsync = Async.AwaitTask(x) + + +let globalRunStartTime = DateTime.UtcNow + + +type ServiceBus.Core.MessageSender with + member inline x.SendRaftJobEvent (jobId: string) (message : ^T when ^T : (static member EventType : string)) = + async { + let raftJobEvent = Raft.Message.RaftEvent.createJobEvent message + let message = ServiceBus.Message(RaftEvent.serializeToBytes raftJobEvent, SessionId = jobId.ToString()) + do! x.SendAsync(message).ToAsync + } + +module CommandLineArguments = + + type ParsedArguments = + { + AgentName: string option + JobId: string option + TaskConfigPath : string option + + JobEventTopicSAS: string option + RestlerPath: string option + WorkDirectory: string option + AppInsightsInstrumentationKey: string option + } + + static member Empty = + { + AgentName = None + JobId = None + TaskConfigPath = None + JobEventTopicSAS = None + RestlerPath = None + WorkDirectory = None + AppInsightsInstrumentationKey = None + } + + let [] AgentName = "--agent-name" + let [] JobId = "--job-id" + let [] TaskConfigFilePath = "--task-config-path" + let [] JobEventTopicSas = "--output-sas" + let [] AppInsights = "--app-insights-instrumentation-key" + let [] RESTlerPath = "--restler-path" + let [] WorkDirectory = "--work-directory" + + let usage = + [ + sprintf "%s " AgentName + sprintf "%s " JobId + sprintf "%s " TaskConfigFilePath + sprintf "%s " JobEventTopicSas + sprintf "%s " AppInsights + sprintf "%s " RESTlerPath + sprintf "%s " WorkDirectory + ] |> (fun args -> String.Join("\n", args)) + + let parseCommandLine (argv: string array) = + if Array.isEmpty argv then + failwithf "Expected command line arguments %s" usage + + let rec parse (currentConfig: ParsedArguments) (args: string list) = + match args with + | [] -> currentConfig + + | AgentName :: agentName :: rest -> + printfn "Agent Name : %s" agentName + parse { currentConfig with AgentName = Some agentName} rest + + | JobId :: jobId :: rest -> + printfn "JobId: %A" jobId + parse { currentConfig with JobId = Some jobId } rest + + | TaskConfigFilePath :: path :: rest -> + printfn "Path to the input job-config: %s" path + parse { currentConfig with TaskConfigPath = Some (path) } rest + + | JobEventTopicSas :: sas :: rest -> + printfn "Sas to job-queue: %s" sas + parse { currentConfig with JobEventTopicSAS = Some (sas) } rest + + | RESTlerPath :: path :: rest -> + printfn "Path to RESTler : %s" path + parse { currentConfig with RestlerPath = Some path } rest + + | AppInsights :: key :: rest -> + printfn "App Insights key: %s" key + parse { currentConfig with AppInsightsInstrumentationKey = Some ( key )} rest + + | WorkDirectory :: path :: rest -> + printfn "Path to RAFT Agent work directory: %s" path + parse { currentConfig with WorkDirectory = Some path } rest + + | arg :: _ -> failwithf "Unhnandled command line parameter: %s" arg + + parse ParsedArguments.Empty (argv |> Array.toList) + + +let downloadFile workDirectory filename (fileUrl: string) = + async { + use httpClient = new Net.Http.HttpClient(BaseAddress = (Uri(fileUrl))) + let! response = httpClient.GetAsync("").ToAsync + if not response.IsSuccessStatusCode then + return failwithf "Get %s request failed due to '%A' (status code: %A)" fileUrl response.ReasonPhrase response.StatusCode + else + use! inputStream = response.Content.ReadAsStreamAsync().ToAsync + + let filePath = workDirectory ++ filename + use fileStream = IO.File.Create(filePath) + do! inputStream.CopyToAsync(fileStream).ToAsync + do! fileStream.FlushAsync().ToAsync + fileStream.Close() + + match Option.ofNullable response.Content.Headers.ContentLength with + | None -> + printfn "Content does not have length set. Ignoring length validation check" + | Some expectedLength when expectedLength > 0L -> + let currentLength = IO.FileInfo(filePath).Length + if currentLength <> expectedLength then + failwithf "Expected length of %s file (%d) does not match what got downloaded (%d)" filePath expectedLength currentLength + | Some expectedLength -> + printfn "Content lengths is set to :%d, so skipping validation since it is not greater than 0" expectedLength + + return filePath + } + +let validateJsonFile (filePath : string) = + try + ignore <| Microsoft.FSharpLu.Json.Compact.deserializeFile filePath + Result.Ok() + with + | ex -> Result.Error (sprintf "Failed to validate %s due to %s. %A" filePath ex.Message ex) + +// Need this for TEST and FUZZ tasks +let createRESTlerEngineParameters + (targetIp, targetPort) (grammarFilePath: string) (mutationsFilePath: string) + (task: Raft.Job.RaftTask) (checkerOptions:(string*string) list) + (runConfiguration: RunConfiguration) : Raft.RESTlerTypes.Engine.EngineParameters = + { + /// File path to the REST-ler (python) grammar. + grammarFilePath = grammarFilePath + + /// File path to the custom fuzzing dictionary. + mutationsFilePath = mutationsFilePath + + /// The IP of the endpoint being fuzzed + targetIp = targetIp + + /// The port of the endpoint being fuzzed + targetPort = targetPort + + /// The maximum fuzzing time in hours + maxDurationHours = task.Duration |> Option.map(fun d -> d.TotalHours) + + /// The authentication options, when tokens are required + refreshableTokenOptions = + match task.AuthenticationMethod with + | Some c -> + let authConfig : Raft.RESTlerTypes.Engine.RefreshableTokenOptions = + { + refreshInterval = Option.defaultValue (int <| TimeSpan.FromHours(1.0).TotalSeconds) runConfiguration.AuthenticationTokenRefreshIntervalSeconds + refreshCommand = + match c with + | Raft.Job.Authentication.TokenRefresh.CommandLine cmd -> cmd + + | Raft.Job.Authentication.TokenRefresh.MSAL secret -> + (sprintf "dotnet /raft-utils/auth/dotnet-core-3.1/AzureAuth.dll msal --secret \"%s\" --prepend-line \"{u'user1':{}}\"" secret) + + | Raft.Job.Authentication.TokenRefresh.TxtToken secret -> + (sprintf "dotnet /raft-utils/auth/dotnet-core-3.1/AzureAuth.dll token --secret \"%s\" --prepend-line \"{u'user1':{}}\"" secret) + } + printfn "Refreshable token configuration : %A" authConfig + Some authConfig + | None -> None + + /// The delay in seconds after invoking an API that creates a new resource + producerTimingDelay = Option.defaultValue 10 runConfiguration.ProducerTimingDelay + + /// The checker options + /// ["enable or disable", "list of specified checkers"] + checkerOptions = checkerOptions + + /// Specifies to use SSL when connecting to the server + useSsl = match runConfiguration.UseSsl with None -> true | Some useSsl -> useSsl + + /// The string to use in overriding the Host for each request + host = task.Host + + /// Path regex for filtering tested endpoints + pathRegex = runConfiguration.PathRegex + } + +type GrammarType = + | Swagger of string + | Json of string + + +let createRESTlerCompilerConfiguration (workDirectory: string) (grammar: GrammarType) (customDictionary: string) (compileConfig: CompileConfiguration ) : Raft.RESTlerTypes.Compiler.Config = + { + swaggerSpecFilePath = match grammar with Swagger path -> Some [path] | Json _ -> None + + // If specified, use this as the input and generate the python grammar. + // This is path to JSON grammar. And we might need to accept as the step to FUZZ task (but do not need it for COMPILE task) + grammarInputFilePath = match grammar with Json path -> Some path | Swagger _ -> None + + grammarOutputDirectoryPath = None + + customDictionaryFilePath = Some customDictionary + + // If specified, update the engine settings with hints derived from the grammar. + engineSettingsFilePath = None + + includeOptionalParameters = true + + useQueryExamples = true + + useBodyExamples = true + + /// When set to 'true', discovers examples and outputs them to a directory next to the grammar. + /// If an existing directory exists, does not over-write it. + discoverExamples = true + + /// The directory where the compiler should look for examples. + /// If 'discoverExamples' is true, this directory will contain the + /// example files that have been discovered. + /// If 'discoverExamples' is false, every time an example is used in the + /// Swagger file, RESTler will first look for it in this directory. + examplesDirectory = workDirectory ++ "Examples" + + /// Perform data fuzzing + dataFuzzing = true + + // When true, only fuzz the GET requests + readOnlyFuzz = compileConfig.ReadOnlyFuzz + + resolveQueryDependencies = true + + resolveBodyDependencies = true + + useRefreshableToken = compileConfig.UseRefreshableToken + + // When true, allow GET requests to be considered. + // This option is present for debugging, and should be + // set to 'false' by default. + // In limited cases when GET is a valid producer, the user + // should add an annotation for it. + allowGetProducers = compileConfig.AllowGetProducers + } + +let inline makeValues< 'T > (stdGen) = + FsCheck.Gen.eval 100 stdGen (FsCheck.Gen.arrayOfLength 10 FsCheck.Arb.generate< 'T >) + +let genMutationsDictionary(rnd: int64) : Raft.RESTlerTypes.Compiler.MutationsDictionary= + let stdGen = FsCheck.Random.mkStdGen(rnd) + + { + restler_fuzzable_string = makeValues(stdGen) |> Array.map (fun s -> s.Get) + restler_fuzzable_int = makeValues(stdGen) |> Array.map(fun n -> sprintf "%d" n) + restler_fuzzable_number = makeValues(stdGen) |> Array.map(fun n -> sprintf "%f" n) + restler_fuzzable_bool = [|"true"; "false"|] + restler_fuzzable_datetime = makeValues(stdGen) |> Array.map (fun dt -> dt.ToString("G")) + restler_fuzzable_object = [|"{}"|] + restler_fuzzable_uuid4 = makeValues(stdGen) |> Array.map (fun g -> sprintf "%A" g) + + restler_custom_payload = Some (dict []) + restler_custom_payload_uuid4_suffix = Some (dict []) + restler_custom_payload_header = None + shadow_values = None + } + +let predefinedMutationsDictionary : Raft.RESTlerTypes.Compiler.MutationsDictionary = + { + restler_fuzzable_string = [|"fuzzstring"|] + restler_fuzzable_int = [|"0" ; "1"|] + restler_fuzzable_number = [|"0.1"; "1.2"|] + restler_fuzzable_bool = [|"true"|] + restler_fuzzable_datetime = [|"6/25/2019 12:00:00 AM"|] + restler_fuzzable_object = [|"{}"|] + restler_fuzzable_uuid4 = [|"903bcc44-30cf-4ea7-968a-d9d0da7c072f"|] + restler_custom_payload = Some (dict []) + restler_custom_payload_uuid4_suffix = Some (dict []) + restler_custom_payload_header = None + shadow_values = None + } + +let createRESTlerCompilerMutations (fsCheckSeed: int64 option) (userConfigurableMutations: CustomDictionary option) : Raft.RESTlerTypes.Compiler.MutationsDictionary= + let m = + match fsCheckSeed with + | Some seed -> + let m = genMutationsDictionary seed + { m with + restler_fuzzable_string = Array.append m.restler_fuzzable_string predefinedMutationsDictionary.restler_fuzzable_string} + | None -> predefinedMutationsDictionary + + match userConfigurableMutations with + | None -> m + + | Some d -> + { + restler_fuzzable_string = + match d.FuzzableString with + | None -> m.restler_fuzzable_string + | Some [||] -> predefinedMutationsDictionary.restler_fuzzable_string + | Some xs -> xs + + restler_fuzzable_int = + match d.FuzzableInt with + | None -> m.restler_fuzzable_int + | Some [||] -> predefinedMutationsDictionary.restler_fuzzable_int + | Some xs -> xs + + restler_fuzzable_number = + match d.FuzzableNumber with + | None -> m.restler_fuzzable_number + | Some [||] -> predefinedMutationsDictionary.restler_fuzzable_number + | Some xs -> xs + + restler_fuzzable_bool = + match d.FuzzableBool with + | None -> m.restler_fuzzable_bool + | Some [||] -> predefinedMutationsDictionary.restler_fuzzable_bool + | Some xs -> xs + + restler_fuzzable_datetime = + match d.FuzzableDatetime with + | None -> m.restler_fuzzable_datetime + | Some [||] -> predefinedMutationsDictionary.restler_fuzzable_datetime + | Some xs -> xs + + restler_fuzzable_object = + match d.FuzzableObject with + | None -> m.restler_fuzzable_object + | Some [||] -> predefinedMutationsDictionary.restler_fuzzable_object + | Some xs -> xs + + restler_fuzzable_uuid4 = + match d.FuzzableUuid4 with + | None -> m.restler_fuzzable_uuid4 + | Some [||] -> predefinedMutationsDictionary.restler_fuzzable_uuid4 + | Some xs -> xs + + restler_custom_payload = d.CustomPayload + restler_custom_payload_uuid4_suffix = d.CustomPayloadUuid4Suffix + restler_custom_payload_header = d.CustomPayloadHeader + shadow_values = d.ShadowValues + } + +type ConsoleMulitplex (log: string -> unit, consoleTextWriter: IO.TextWriter) = + inherit IO.TextWriter() + + let sb = Text.StringBuilder() + + override _.Write(s:string)= + consoleTextWriter.Write(s) + sb.Append s |> ignore + + override _.WriteLine() = + consoleTextWriter.WriteLine() + log(sb.ToString()) + sb.Clear() |> ignore + + override _.Encoding = Console.OutputEncoding + +let multiplexConsole (workDirectory: string) (jobId: string) (agentName: string) = + let workDirectory = + if IO.Directory.Exists workDirectory then + workDirectory + else + "." + + let stdOutToFile s = + let p = workDirectory ++ "stdout-agent.txt" + IO.File.AppendAllLines(p, [s]) + + let stdErrToFile s = + let p = workDirectory ++ "stderr-agent.txt" + IO.File.AppendAllLines(p, [s]) + + Console.SetOut(new ConsoleMulitplex((fun s -> stdOutToFile s), Console.Out)) + Console.SetError(new ConsoleMulitplex((fun s -> stdErrToFile s), Console.Error)) + + +let copyDir srcDir destDir (doNotOverwriteFilePaths: string Set) = + if srcDir = destDir then + printfn "Source and destination is the same directory (%s). Skipping copy" srcDir + else + let rec doCopyDir src dest = + let srcDir = IO.DirectoryInfo(src) + if not srcDir.Exists then + failwithf "Directory not found: %s" srcDir.FullName + + let destDir = IO.DirectoryInfo(dest) + if not destDir.Exists then + destDir.Create() + + for f in srcDir.GetFiles() do + let destFilePath = destDir.FullName ++ f.Name + if not (doNotOverwriteFilePaths.Contains destFilePath && IO.File.Exists destFilePath) then + f.CopyTo(destFilePath, true) |> ignore + + for d in srcDir.GetDirectories() do + doCopyDir d.FullName (destDir.FullName ++ d.Name) + doCopyDir srcDir destDir + +[] +let main argv = + printfn "Arguments: %A" argv + let agentConfiguration = CommandLineArguments.parseCommandLine argv + let appInsights = + match agentConfiguration.AppInsightsInstrumentationKey with + | None -> failwith "AppInsights configuration is not set" + | Some instrumentationKey -> + Microsoft.ApplicationInsights.TelemetryClient(new Extensibility.TelemetryConfiguration(instrumentationKey), InstrumentationKey = instrumentationKey) + + let jobId = + match agentConfiguration.JobId with + | None -> failwith "JobId is not set" + | Some jobId -> jobId + + let agentName = + match agentConfiguration.AgentName with + | None -> failwith "Agent name is not set" + | Some agentName -> agentName + + let workDirectory = + match agentConfiguration.WorkDirectory with + | None -> failwithf "Work directory is not set" + | Some p -> p + + multiplexConsole workDirectory jobId agentName + + let jobEventSender = + match agentConfiguration.JobEventTopicSAS with + | None -> failwith "Job status connection is not set" + | Some sas -> + ServiceBus.Core.MessageSender(ServiceBus.ServiceBusConnectionStringBuilder(sas), ServiceBus.RetryPolicy.Default) + + async { + if not <| IO.Directory.Exists workDirectory then + appInsights.TrackTrace((sprintf "Workd directory does not exist: %s" workDirectory), + DataContracts.SeverityLevel.Error, + dict ["jobId", jobId; "agentName", agentName]) + failwithf "Failing since work directory does not exist: %s" workDirectory + + let taskConfigurationPath = + match agentConfiguration.TaskConfigPath with + | Some path -> path + | None -> failwith "Job configuration is not set" + + + let restlerPath = + match agentConfiguration.RestlerPath with + | None -> failwith "RESTler path is not set" + | Some p -> p + + match Raft.RESTlerDriver.validateRestlerComponentsPresent restlerPath with + | Result.Ok() -> () + | Result.Error err -> failwith err + + let task: Raft.Job.RaftTask = Json.Compact.deserializeFile taskConfigurationPath + let restlerPayload : RESTlerPayload = Json.Compact.deserialize (task.ToolConfiguration.ToString()) + + do! jobEventSender.SendRaftJobEvent jobId + ({ + AgentName = agentName + Metadata = None + Tool = "RESTler" + JobId = jobId + State = Raft.JobEvents.Created + + Metrics = None + UtcEventTime = System.DateTime.UtcNow + Details = None + }: Raft.JobEvents.JobStatus) + + printfn "Got job configuration message: %A" restlerPayload + + let customDictionaryPath = workDirectory ++ "customDictionary.json" + let grammarPy = workDirectory ++ "grammar.py" + let dictJson = workDirectory ++ "dict.json" + + let compileSwaggerGrammar(compilerConfiguration) = + async { + let! swagger = + async { + match task.SwaggerLocation with + | Raft.Job.SwaggerLocation.URL url -> + let! swagger = downloadFile workDirectory "swagger.json" url + printfn "Downloaded swagger spec to :%s" swagger + return swagger + | Raft.Job.FilePath path -> + return path + } + + match validateJsonFile swagger with + | Result.Ok () -> () + | Result.Error (err) -> failwithf "File %s is not a valid JSON file due to %s" swagger err + + let compilerConfig = createRESTlerCompilerConfiguration workDirectory (Swagger swagger) customDictionaryPath compilerConfiguration + do! Raft.RESTlerDriver.compile restlerPath workDirectory compilerConfig + } + + let compileJsonGrammar (jsonGrammarPath: string) (compilerConfiguration) = + async { + match validateJsonFile jsonGrammarPath with + | Result.Ok() -> () + | Result.Error (err) -> + failwithf "File %s is not a valid JSON file due to %s (make sure that you set CompileFolder path parameter in config JSON)" jsonGrammarPath err + + let compilerConfig = createRESTlerCompilerConfiguration workDirectory (Json jsonGrammarPath) customDictionaryPath compilerConfiguration + do! Raft.RESTlerDriver.compile restlerPath workDirectory compilerConfig + } + + let report state (summary: Raft.JobEvents.RunSummary option) = + async { + printfn "Reporting summary [%A]: %A" state summary + do! jobEventSender.SendRaftJobEvent jobId + ({ + AgentName = agentName + Metadata = None + Tool = "RESTler" + JobId = jobId + State = state + + Metrics = summary + UtcEventTime = System.DateTime.UtcNow + Details = None + } : Raft.JobEvents.JobStatus) + } + + let onBugFound (bugDetails : Raft.JobEvents.RESTlerBugDetails) = + async { + printfn "OnBugFound %A" bugDetails + do! jobEventSender.SendRaftJobEvent jobId + ({ + Tool = "RESTler" + JobId = jobId + AgentName = agentName + Metadata = None + BugDetails = bugDetails + } : Raft.JobEvents.RESTlerBugDetails Raft.JobEvents.BugFound) + } + + let getResultReportingInterval() = + let resultAnalyzerReportInterval = + let defaultInterval = TimeSpan.FromSeconds(60.0) + match restlerPayload.AgentConfiguration with + | Some agentConfig -> + match agentConfig.ResultsAnalyzerReportTimeSpanInterval, task.Duration with + | None, _ -> + printfn "Result analyzer interval is not set, using default" + Some defaultInterval + | Some ts, Some duration when ts >= duration -> + printfn "Result analyzer interval (%A) is longer than job duration (%A). Using this as not set" ts duration + None + | Some ts, _ -> + printfn "Result analyzer interval is set to %A" ts + Some ts + | None -> Some defaultInterval + resultAnalyzerReportInterval + + let getIpAndPort (host: string option) (runConfiguration: RunConfiguration) = + async { + match host, runConfiguration.TargetEndpointConfiguration with + | None, None -> + printf "Host is not set, Target Endpoint Configuration is not set" + return "", 80 + | Some host, None -> + let targetPort = + match runConfiguration.UseSsl with + | None -> 443 + | Some useSsl -> if useSsl then 443 else 80 + let! dns = System.Net.Dns.GetHostAddressesAsync(host) |> Async.AwaitTask + printfn "Following IP addresses got retrived for the host %s : %A. Going to use first one" host dns + if Array.isEmpty dns then + printfn "Array of host addresses returned by DNS is empty" + return "", 80 + else + return dns.[0].ToString(), targetPort + | _, Some endpointConfiguration -> + printfn "Endpoing configuration is set, going to use it: %A" endpointConfiguration + return endpointConfiguration.Ip, endpointConfiguration.Port + } + + let test (testType: string) checkerOptions (jobConfiguration: RunConfiguration) = + async { + let resultAnalyzerReportInterval = getResultReportingInterval() + let! targetIp, targetPort = getIpAndPort task.Host jobConfiguration + let engineParameters = createRESTlerEngineParameters (targetIp, targetPort) grammarPy dictJson task checkerOptions jobConfiguration + printfn "Starting RESTler test task" + do! Raft.RESTlerDriver.test testType restlerPath workDirectory engineParameters onBugFound (report Raft.JobEvents.JobState.Running) (globalRunStartTime, resultAnalyzerReportInterval) + } + + let fuzz (fuzzType:string) checkerOptions (jobConfiguration: RunConfiguration) = + async { + let resultAnalyzerReportInterval = getResultReportingInterval() + let! targetIp, targetPort = getIpAndPort task.Host jobConfiguration + let engineParameters = createRESTlerEngineParameters (targetIp, targetPort) grammarPy dictJson task checkerOptions jobConfiguration + printfn "Starting RESTler fuzz task" + do! Raft.RESTlerDriver.fuzz fuzzType restlerPath workDirectory engineParameters onBugFound (report Raft.JobEvents.JobState.Running) (globalRunStartTime, resultAnalyzerReportInterval) + } + + let replay replayLogFile (jobConfiguration: RunConfiguration) = + async { + //same command line parameters as fuzzing, except for fuzzing parameter pass sprintf "--replay_log %s" replayLogFilePath + let! targetIp, targetPort = getIpAndPort task.Host jobConfiguration + let engineParameters = createRESTlerEngineParameters (targetIp, targetPort) grammarPy dictJson task [] jobConfiguration + printfn "Starting RESTler replay task" + return! Raft.RESTlerDriver.replay restlerPath workDirectory replayLogFile engineParameters + } + + // Start RESTler process with following flags + // compile, test, fuzz + // --telemetryRootDirPath + let! state, details, exitCode, summary = + async { + try + match restlerPayload.Task with + | TaskType.Compile -> + let compileConfiguration = + match restlerPayload.CompileConfiguration with + | Some compileConfiguration -> compileConfiguration + | None -> + // Return a default compilerConfiguration type + { InputJsonGrammarPath = None + InputFolderPath = None + ReadOnlyFuzz = false + AllowGetProducers = false + UseRefreshableToken = false + MutationsSeed = None + CustomDictionary = None } + + let restlerCompatibleMutations = + createRESTlerCompilerMutations compileConfiguration.MutationsSeed compileConfiguration.CustomDictionary + + restlerCompatibleMutations |> Json.Compact.serializeToFile customDictionaryPath + + match compileConfiguration.InputFolderPath with + | Some path -> copyDir path workDirectory (set [taskConfigurationPath]) + | None -> () + + match compileConfiguration.InputJsonGrammarPath with + | None -> do! compileSwaggerGrammar compileConfiguration + | Some p -> do! compileJsonGrammar (workDirectory ++ p) compileConfiguration + let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime + return Raft.JobEvents.Completed, None, 0, summary + + | TaskType.Test -> + printfn "Running directed-smoke-test" + match restlerPayload.RunConfiguration with + | None -> return failwithf "Job-run configuration is not set for Test task for job payload: %A" restlerPayload + | Some jobConfiguration -> + copyDir jobConfiguration.InputFolderPath workDirectory (set [taskConfigurationPath]) + do! report Raft.JobEvents.Running None + do! test "directed-smoke-test" [] jobConfiguration + let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime + return Raft.JobEvents.Completed, None, 0, summary + + | TaskType.TestFuzzLean -> + printfn "Running directed-smoke-test" + match restlerPayload.RunConfiguration with + | None -> return failwithf "Job-run configuration is not set for Test task for job payload: %A" restlerPayload + | Some jobConfiguration -> + copyDir jobConfiguration.InputFolderPath workDirectory (set [taskConfigurationPath]) + do! report Raft.JobEvents.Running None + let fuzzLeanCheckers = + [ + ("--enable_checkers", "*") + ("--disable_checkers", "namespacerule") + ] + do! test "directed-smoke-test" fuzzLeanCheckers jobConfiguration + let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime + return Raft.JobEvents.Completed, None, 0, summary + + | TaskType.Fuzz -> + printfn "Running bfs fuzz" + match restlerPayload.RunConfiguration with + | None -> return failwithf "Job-run configuration is not set for Compile task for job payload: %A" restlerPayload + | Some jobConfiguration -> + copyDir jobConfiguration.InputFolderPath workDirectory (set [taskConfigurationPath]) + do! report Raft.JobEvents.Running None + let allCheckers = ["--enable_checkers", "*"] + do! fuzz "bfs" allCheckers jobConfiguration + let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime + return Raft.JobEvents.Completed, None, 0, summary + + | TaskType.FuzzBfsCheap -> + printfn "Running bfs-cheap fuzz" + match restlerPayload.RunConfiguration with + | None -> return failwithf "Job-run configuration is not set for Test task for job payload: %A" restlerPayload + | Some jobConfiguration -> + copyDir jobConfiguration.InputFolderPath workDirectory (set [taskConfigurationPath]) + do! report Raft.JobEvents.Running None + let allCheckers = ["--enable_checkers", "*"] + do! fuzz "bfs-cheap" allCheckers jobConfiguration + let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime + return Raft.JobEvents.Completed, None, 0, summary + + | TaskType.FuzzRandomWalk -> + printfn "Running random-walk fuzz" + match restlerPayload.RunConfiguration with + | None -> return failwithf "Job-run configuration is not set for Compile task for job payload: %A" restlerPayload + | Some jobConfiguration -> + copyDir jobConfiguration.InputFolderPath workDirectory (set [taskConfigurationPath]) + do! report Raft.JobEvents.Running None + let allCheckers = ["--enable_checkers", "*"] + do! fuzz "random-walk" allCheckers jobConfiguration + let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime + return Raft.JobEvents.Completed, None, 0, summary + + | TaskType.Replay -> + match restlerPayload.RunConfiguration with + | None -> return failwithf "Replay configuration is not set for Compile task for job payload: %A" restlerPayload + | Some replayRunConfiguration -> + let replaySourcePath = replayRunConfiguration.InputFolderPath + do! report Raft.JobEvents.Running None + + let replayAndReport (bugs: IO.FileInfo seq) = + async { + let replaySummaryDetails = ResizeArray() + for bug in bugs do + printfn "Running replay on %s" bug.FullName + let! replaySummary = replay bug.FullName replayRunConfiguration + let summary = + match replaySummary with + | None -> + sprintf "%s : No results" bug.Name + | Some s -> + sprintf "%s: %A" bug.Name (s.ResponseCodeCounts |> Map.toList) + + replaySummaryDetails.Add(summary) + do! jobEventSender.SendRaftJobEvent jobId + ({ + AgentName = agentName + Metadata = None + Tool = "RESTler" + JobId = jobId + State = Raft.JobEvents.JobState.Running + Metrics = None + UtcEventTime = System.DateTime.UtcNow + Details = Some (Seq.cast replaySummaryDetails) + } : Raft.JobEvents.JobStatus) + + return replaySummaryDetails + } + + let replayAll () = + async { + let restlerResults = IO.DirectoryInfo(replaySourcePath ++ "RestlerResults") + if restlerResults.Exists then + let experiments = restlerResults.EnumerateDirectories("experiment*") + let bugBuckets = IO.DirectoryInfo((Seq.head experiments).FullName ++ "bug_buckets") + if bugBuckets.Exists then + let! details = replayAndReport (bugBuckets.EnumerateFiles()) + return Some details + else + return None + else + return None + } + let! details = + match restlerPayload.ReplayConfiguration with + | None -> replayAll() + | Some replayConfiguration -> + async { + match replayConfiguration.ReplayBugBucketsPaths with + | Some paths -> + let details = ResizeArray() + for path in paths do + let fullPath = replaySourcePath ++ path + printfn "Full path: %s" fullPath + + let file = IO.FileInfo(fullPath) + let dir = IO.DirectoryInfo(fullPath) + + if file.Exists then + printfn "%s is a file, running replay..." fullPath + let! d = replayAndReport [file] + details.AddRange d + else if dir.Exists then + printfn "%s is a directory, running replay on every file..." fullPath + let! d = replayAndReport (dir.EnumerateFiles() |> Seq.filter Raft.RESTlerDriver.isBugFile) + details.AddRange d + else + failwithf "Cannot run replay since could not find %s" fullPath + return Some details + | None -> return! replayAll() + } + return Raft.JobEvents.Completed, (details |> Option.map Seq.cast), 0, None + with + | ex -> + printfn "%A" ex + let! summary = Raft.RESTlerDriver.processRunSummary workDirectory globalRunStartTime + return Raft.JobEvents.Error, (Some (seq[ex.Message])), 1, summary + } + + printfn "Sending final event: %A with summary: %A and details %A" state summary details + do! jobEventSender.SendRaftJobEvent jobId + ({ + AgentName = agentName + Metadata = None + Tool = "RESTler" + JobId = jobId + State = state + Metrics = summary + UtcEventTime = System.DateTime.UtcNow + Details = details + } : Raft.JobEvents.JobStatus) + + return exitCode + } + |> Async.Catch + |> fun result -> + async { + let! res = + async { + match! result with + | Choice1Of2 r -> + return r + | Choice2Of2 ex -> + eprintf "Raft.Agent failed due to: %A" ex + appInsights.TrackException(ex, dict ["JobId", sprintf "%A" jobId; "AgentName", agentName]) + + do! jobEventSender.SendRaftJobEvent jobId + ({ + AgentName = agentName + Metadata = None + Tool = "RESTler" + JobId = jobId + State = Raft.JobEvents.Error + Metrics = None + UtcEventTime = System.DateTime.UtcNow + Details = Some (seq [ex.Message]) + } : Raft.JobEvents.JobStatus) + + do! System.Console.Error.FlushAsync().ToAsync + do! System.Console.Out.FlushAsync().ToAsync + return 2 + } + appInsights.Flush() + do! jobEventSender.CloseAsync().ToAsync + return res + } + |> Async.RunSynchronously diff --git a/src/Agent/RESTlerAgent/RESTlerAgentConfigTypes.fs b/src/Agent/RESTlerAgent/RESTlerAgentConfigTypes.fs new file mode 100644 index 0000000..3cafeab --- /dev/null +++ b/src/Agent/RESTlerAgent/RESTlerAgentConfigTypes.fs @@ -0,0 +1,140 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +module RESTlerAgentConfigTypes +open System.Collections.Generic + +type CustomDictionary = + { + // + // if None and FSCheck seed is set then random values are used + // if None and FSCheck seed is not set, then hard-coded RESTler default values are used + // if [] then hard-coded RESTler default values are used + FuzzableString : string array option + FuzzableInt : string array option + FuzzableNumber : string array option + FuzzableBool : string array option + FuzzableDatetime : string array option + FuzzableObject : string array option + FuzzableUuid4 : string array option + // + + CustomPayload : IDictionary option + CustomPayloadUuid4Suffix : IDictionary option + CustomPayloadHeader : IDictionary option + ShadowValues : IDictionary> option + } + +/// User-specified compiler configuration +type CompileConfiguration = + { + //relative path to a JSON grammar to use for compilation relative to compile folder path + //if set then JSON grammar used for compilation instead of Swagger + InputJsonGrammarPath: string option + + /// Grammar is produced by compile step. The compile step + /// file share is mounted and set here. Agent will not modify + /// this share. Agent will make a copy of all needed files to it's work directory. + InputFolderPath: string option + + + // When true, only fuzz the GET requests + ReadOnlyFuzz : bool + + // When true, allow GET requests to be considered. + // This option is present for debugging, and should be + // set to 'false' by default. + // In limited cases when GET is a valid producer, the user + // should add an annotation for it. + AllowGetProducers : bool + + // authentication token refreshed on a timer + UseRefreshableToken : bool + + // if Some seed then it will be used to populate customDictitonary fields (see CustomDictionary type for logic on how the values are set) + // if None - then default hard-coded RESTler values are used for populating customDictionary fields + MutationsSeed : int64 option + + CustomDictionary: CustomDictionary option + } + +type ReplayConfiguration = + { + //list of paths to RESTler folder runs to replay (names of folders are assigned when mounted readonly/readwrite file share mounts) + // if path is a folder, then all bug buckets replayed in the folder + // if path is a bug_bucket file - then only that file is replayed. + + // if empty - then replay all bugs under jobRunConfiguration.previousStepOutputFolderPath + ReplayBugBucketsPaths : string array option + } + +type TargetEndpointConfiguration = + { + /// The IP of the endpoint being fuzzed + Ip: string + + /// The port of the endpoint being fuzzed + Port: int + } + +type RunConfiguration = + { + /// Path to grammar py relative to compile folder path. If not set then default "grammar.py" grammar is assumed + GrammarPy: string option + + /// For Test of Fuzz tasks: Grammar is produced by compile step. The compile step + /// file share is mounted and set here. Agent will not modify + /// this share. Agent will make a copy of all needed files to it's work directory. + /// For Replay task: path to RESTler Fuzz or Test run that contains bug buckets to replay + InputFolderPath: string + + // endpoint configuration required when running fuzz or test tasks + TargetEndpointConfiguration: TargetEndpointConfiguration option + + /// The delay in seconds after invoking an API that creates a new resource + ProducerTimingDelay : int option + + /// Specifies to use SSL when connecting to the server + UseSsl : bool option + + /// Token Refresh Interval + AuthenticationTokenRefreshIntervalSeconds: int option + + /// Path regex for filtering tested endpoints + PathRegex : string option + } + + + +type AgentConfiguration = + { + // If not set then result analyzer will run only once after RESTler exits + ResultsAnalyzerReportTimeSpanInterval : System.TimeSpan option + } + +type TaskType = + | Compile + | Test + | TestFuzzLean + | Fuzz + | FuzzRandomWalk + | FuzzBfsCheap + | Replay + + +type RESTlerPayload = + { + Task: TaskType + + //Compile task type configuration + CompileConfiguration: CompileConfiguration option + //Fuzz or Test task type configuration + RunConfiguration : RunConfiguration option + //Replay task type configuration + ReplayConfiguration : ReplayConfiguration option + + //overall agent configuration + AgentConfiguration : AgentConfiguration option + } + + diff --git a/src/Agent/RESTlerAgent/RESTlerDriver.fs b/src/Agent/RESTlerAgent/RESTlerDriver.fs new file mode 100644 index 0000000..b4b0574 --- /dev/null +++ b/src/Agent/RESTlerAgent/RESTlerDriver.fs @@ -0,0 +1,523 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +module Raft.RESTlerDriver + +open System +open Microsoft.FSharpLu + +module private RESTlerInternal = + let inline (++) (path1: string) (path2 : string) = IO.Path.Join(path1, path2) + + module Runtime = + let [] DotNet = "dotnet" + + let [] Python = "python3" + + + module Paths = + let compiler (restlerRootDirectory: string) = + restlerRootDirectory ++ "compiler" ++ "Restler.CompilerExe.dll" + + let restler (restlerRootDirectory) = + restlerRootDirectory ++ "engine" ++ "restler.pyc" + + let resultAnalyzer = + "/raft" ++ "result-analyzer" ++ "RaftResultAnalyzer.dll" + + + (* + let SupportedCheckers = + [ + "leakagerule" + "resourcehierarchy" + "useafterfree" + "namespacerule" + "invaliddynamicobject" + "payloadbody" + "*" + ] + *) + + + type ProcessResult = + { + ExitCode : int option + ProcessId : int + } + + let startProcessAsync command arguments workingDir (stdOutFilePath: string option) (stdErrFilePath: string option) = + async { + use instance = + new Diagnostics.Process( + StartInfo = + Diagnostics.ProcessStartInfo + ( + FileName = command, + WorkingDirectory = workingDir, + Arguments = arguments, + CreateNoWindow = false, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true + ), + EnableRaisingEvents = true + ) + + use instanceTerminated = new System.Threading.AutoResetEvent(false) + use noMoreOutput = new System.Threading.AutoResetEvent(false) + use noMoreError = new System.Threading.AutoResetEvent(false) + + // Note: it's important to register this event __before__ calling instance.Start() + // to avoid a deadlock if the process terminates too quickly... + instance.Exited.Add + (fun _ -> + if not instanceTerminated.SafeWaitHandle.IsClosed && not instanceTerminated.SafeWaitHandle.IsInvalid then + instanceTerminated.Set() |> ignore + ) + + + // Standard output must be read prior to waiting on the instance to exit. + // Otherwise, a deadlock is created when the child process has filled its output + // buffer and waits for the parent to consume it, and the parent waits for the + // child process to exit first. + // Reference: https://stackoverflow.com/questions/139593/processstartinfo-hanging-on-waitforexit-why?lq=1 + use stdOutFile = + match stdOutFilePath with + | Some path -> System.IO.File.CreateText(path) :> IO.TextWriter + | None -> IO.TextWriter.Null + use stdErrFile = + match stdErrFilePath with + | Some path -> System.IO.File.CreateText(path) :> IO.TextWriter + | None -> IO.TextWriter.Null + + let appendHandler + (endOfStreamEvent:System.Threading.AutoResetEvent) + (aggregator:IO.TextWriter) + (dataReceived:Diagnostics.DataReceivedEventArgs) = + if isNull dataReceived.Data then + if not endOfStreamEvent.SafeWaitHandle.IsClosed && not endOfStreamEvent.SafeWaitHandle.IsInvalid then + endOfStreamEvent.Set() |> ignore + else + aggregator.WriteLine(dataReceived.Data) |> ignore + + instance.OutputDataReceived.Add(appendHandler noMoreOutput stdOutFile) + instance.ErrorDataReceived.Add(appendHandler noMoreError stdErrFile) + + printfn "Running process with arguments : %s and argument list : %A" instance.StartInfo.Arguments instance.StartInfo.ArgumentList + + if instance.Start() then + instance.BeginOutputReadLine() + instance.BeginErrorReadLine() + + let! _ = Async.Parallel [ Async.AwaitWaitHandle instanceTerminated; Async.AwaitWaitHandle noMoreOutput; Async.AwaitWaitHandle noMoreError ] + + let exitCode = + try + Some instance.ExitCode + with :? System.InvalidOperationException -> + printfn "Ether process has not exited or process handle is not valid: '%O %O'" command arguments + None + + try + do! stdOutFile.FlushAsync() |> Async.AwaitTask + with ex -> + printfn "Failed to flush stdoout due to %A" ex + + try + do! stdErrFile.FlushAsync() |> Async.AwaitTask + with ex -> + printfn "Failed to flush stderr due to %A" ex + + stdOutFile.Close() + stdErrFile.Close() + + return + { + ProcessId = instance.Id + ExitCode = exitCode + } + else + return failwithf "Could not start command: '%s' with parameters '%s'" command arguments + } + + let getRunExperimentFolder (fuzzingWorkingDirectory) (runStartTime: DateTime) = + let restlerResults = IO.DirectoryInfo(fuzzingWorkingDirectory ++ "RestlerResults") + if restlerResults.Exists then + let experiments = restlerResults.EnumerateDirectories("experiment*") + if Seq.isEmpty experiments then + None + else + let startedExperiments = + experiments + |> Seq.filter ( fun e -> e.CreationTimeUtc >= runStartTime) + |> Seq.sortBy ( fun e -> e.CreationTimeUtc ) + + if (Seq.length startedExperiments > 1) then + printfn "There are : %d [%A] that have been create past %A. Using one closest to start time of this run." + (Seq.length startedExperiments) startedExperiments runStartTime + startedExperiments |> Seq.tryHead + else + None + + /// Runs the results analyzer. Note: the results analyzer searches for all + /// logs in the specified root directory + let runResultsAnalyzer fuzzingWorkingDirectory runStartTime = + async { + let resultsAnalyzer = Paths.resultAnalyzer + if not (IO.File.Exists resultsAnalyzer) then + failwith "Could not find path to RESTler results analyzer." + + match getRunExperimentFolder fuzzingWorkingDirectory runStartTime with + | Some experimentFolder -> + let! summaryPath = + async { + let restlerExperimentLogs = experimentFolder.FullName ++ "logs" + let bug_buckets = experimentFolder.FullName ++ "bug_buckets" ++ "bug_buckets.txt" + if IO.Directory.Exists restlerExperimentLogs then + let resultsAnalyzerParameters = + [ + sprintf "--restler-results-folder \"%s\"" restlerExperimentLogs + sprintf "--bug-buckets \"%s\"" bug_buckets + ] + let resultsAnalyzerCmdLine = resultsAnalyzerParameters |> String.concat " " + let! result = + startProcessAsync + Runtime.DotNet + (sprintf "\"%s\" %s" resultsAnalyzer resultsAnalyzerCmdLine) + fuzzingWorkingDirectory + (Some (fuzzingWorkingDirectory ++ "stdout-resultsAnalyzer.txt")) + (Some (fuzzingWorkingDirectory ++ "stderr-resultsAnalyzer.txt")) + + match result.ExitCode with + | Some exitCode -> + if exitCode <> 0 then + printfn "Results analyzer for logs in %s failed." fuzzingWorkingDirectory + | None -> + printfn "Result Analyzer did not produce exit code" + + let summaryPath = restlerExperimentLogs ++ "raft-analyzer-summary.json" + + if IO.File.Exists summaryPath then + return Some summaryPath + else + eprintfn "RESTLER Summary file was not found: %s" summaryPath + return None + else + return None + } + return Some summaryPath + | None -> + return None + } + + let runRestlerEngine restlerRootPath workingDirectory (engineArguments: string seq) = + async { + let restlerPyPath = Paths.restler restlerRootPath + + if not (IO.File.Exists restlerPyPath) then + failwith "Could not find path to RESTler engine." + + let restlerParameterCmdLine = engineArguments |> String.concat " " + + let engineStdErr = workingDirectory ++ "stderr-RESTlerEngine.txt" + let engineStdOut = workingDirectory ++ "stdout-RESTlerEngine.txt" + + printfn "Running restler with command line : %s" restlerParameterCmdLine + + let! result = + startProcessAsync + Runtime.Python + (sprintf "-B \"%s\" %s" restlerPyPath restlerParameterCmdLine) + workingDirectory + (Some engineStdOut) + (Some engineStdErr) + + match result.ExitCode with + | Some exitCode -> + if exitCode = -1 then + failwithf "RESTler caught an unhandled exception. See %s for more information." engineStdOut + else if exitCode <> 0 then + failwithf "RESTler engine failed. See logs in %s directory for more information." workingDirectory + | None -> + printfn "RESTler engine did not produce exit code" + + let engineError = IO.FileInfo(engineStdErr) + if engineError.Length > 0L then + failwithf "RESTler engined failed. See RESTler error log %s for more information." engineStdErr + } + + let compile restlerRootDirectory (workingDirectory: string) (config:Raft.RESTlerTypes.Compiler.Config) = + async { + let compilerPath = Paths.compiler restlerRootDirectory + if not (IO.File.Exists compilerPath) then + failwith "Could not find path to compiler. Please re-install RESTler or contact support." + + let compilerConfigPath = workingDirectory ++ "config.json" + let compilerConfig = + { config with + grammarOutputDirectoryPath = Some workingDirectory + customDictionaryFilePath = config.customDictionaryFilePath } + Json.Compact.serializeToFile compilerConfigPath compilerConfig + + // Run compiler + let! result = + startProcessAsync + Runtime.DotNet + (sprintf "\"%s\" \"%s\"" compilerPath compilerConfigPath) + workingDirectory + (Some (workingDirectory ++ "stdout-RESTlerCompiler.txt")) + (Some (workingDirectory ++ "stderr-RESTlerCompiler.txt")) + + match result.ExitCode with + | Some exitCode -> + if exitCode <> 0 then + failwithf "Compiler failed. See logs in %s directory for more information. " workingDirectory + | None -> + failwithf "Compiler did not produce and exit code" + } + + + /// Gets the RESTler engine parameters common to any fuzzing mode + let getCommonParameters workingDirectory (fuzzingMode: string option) (parameters:Raft.RESTlerTypes.Engine.EngineParameters) = + let settings = Raft.RESTlerTypes.Engine.Settings.FromEngineParameters fuzzingMode parameters + let settingsFilePath = workingDirectory ++ "settings.json" + Json.Compact.serializeToFile settingsFilePath settings + [ + sprintf "--settings %s" settingsFilePath + sprintf "--restler_grammar \"%s\"" parameters.grammarFilePath + sprintf "--custom_mutations \"%s\"" parameters.mutationsFilePath + + // Checkers + (if parameters.checkerOptions.Length > 0 then + parameters.checkerOptions + |> List.map (fun (x, y) -> sprintf "%s %s" x y) + |> String.concat " " + else "") + "--set_version 'restler/6.0.0'" + ] + + let validateAuthentication workingDirectory (tokenOptions : RESTlerTypes.Engine.RefreshableTokenOptions) = + async { + printfn "Validating authentication configuration" + let cmd, args = "/bin/sh", sprintf "-c \"%s\"" tokenOptions.refreshCommand + + let! r = startProcessAsync cmd args "." None (Some(workingDirectory ++ "stderr-auth.txt")) + match r.ExitCode with + | Some 0 -> return () + | None | Some _ -> + return failwithf "Failed to validate Authentication configuration. Please see stdout-auth.txt and stderr-auth.txt for errors." + } + + let test testType restlerRootDirectory workingDirectory (parameters: Raft.RESTlerTypes.Engine.EngineParameters) = + async { + do! + match parameters.refreshableTokenOptions with + | None -> async.Return() + | Some t -> validateAuthentication workingDirectory t + + let testParameters = getCommonParameters workingDirectory (Some testType) parameters + do! runRestlerEngine restlerRootDirectory workingDirectory testParameters + } + + + let fuzz fuzzType restlerRootDirectory workingDirectory (parameters: Raft.RESTlerTypes.Engine.EngineParameters) = + async { + do! + match parameters.refreshableTokenOptions with + | None -> async.Return() + | Some t -> validateAuthentication workingDirectory t + + let fuzzingParameters = getCommonParameters workingDirectory (Some fuzzType) parameters + do! runRestlerEngine restlerRootDirectory workingDirectory fuzzingParameters + } + + let replay restlerRootDirectory workingDirectory replayLogFilePath (parameters: Raft.RESTlerTypes.Engine.EngineParameters) = + async { + do! + match parameters.refreshableTokenOptions with + | None -> async.Return() + | Some t -> validateAuthentication workingDirectory t + + let replayParameters = + (getCommonParameters workingDirectory None parameters) + @ + [ + sprintf "--replay_log %s" replayLogFilePath + ] + + do! runRestlerEngine restlerRootDirectory workingDirectory replayParameters + } + +// Call this first to make sure that we have everything we need to even start fuzzing in the first place +let validateRestlerComponentsPresent (restlerRootDirectory: string) = + let restlerPyPath = RESTlerInternal.Paths.restler restlerRootDirectory + if not (IO.File.Exists restlerPyPath) then + Result.Error "Could not find path to RESTler engine." + else + let resultsAnalyzer = RESTlerInternal.Paths.resultAnalyzer + if not (IO.File.Exists resultsAnalyzer) then + Result.Error "Could not find path to RESTler results analyzer" + else + let compilerPath = RESTlerInternal.Paths.compiler restlerRootDirectory + if not (IO.File.Exists compilerPath) then + Result.Error "Could not find path to RESTler compiler." + else + Result.Ok () + +let compile restlerRootDirectory workingDirectory config = + RESTlerInternal.compile restlerRootDirectory workingDirectory config + + +type ReportRunSummary = Raft.JobEvents.RunSummary option -> Async +let inline (++) (path1: string) (path2 : string) = IO.Path.Join(path1, path2) + +let processRunSummary workingDirectory runStartTime = + async { + match! RESTlerInternal.runResultsAnalyzer workingDirectory runStartTime with + | None -> + return None + | Some runSummaryPath -> + let summary = + match runSummaryPath with + | None -> + Raft.JobEvents.RunSummary.Empty + | Some path -> + match Json.Compact.tryDeserializeFile path with + | Choice1Of2 (runSummary: Raft.JobEvents.RunSummary) -> + runSummary + | Choice2Of2 err -> + eprintfn "Failed to process run summary: %s" err + Raft.JobEvents.RunSummary.Empty + return Some summary + } + +let resultAnalyzer workingDirectory (token: Threading.CancellationToken) (report: ReportRunSummary) (runStartTime: DateTime, reportInterval: TimeSpan option) = + let rec analyze() = + async { + if token.IsCancellationRequested then + let! summary = processRunSummary workingDirectory runStartTime + printfn "Reporting summary one last time before exiting: %A" summary + do! report summary + return () + else + match reportInterval with + | None -> + printfn "Interval reporting is not enabled. Will only report results at the end of the run." + let! _ = Async.AwaitWaitHandle(token.WaitHandle) + return! analyze() + | Some interval -> + let! summary = processRunSummary workingDirectory runStartTime + do! report summary + let! _ = Async.AwaitWaitHandle(token.WaitHandle, int interval.TotalMilliseconds) + return! analyze() + } + analyze() + +let isBugFile (file: IO.FileInfo) = + file.Name <> "bug_buckets.txt" + +let bugFoundPollInterval = TimeSpan.FromSeconds (10.0) +type OnBugFound = JobEvents.RESTlerBugDetails -> Async +let pollForBugFound workingDirectory (token: Threading.CancellationToken) (runStartTime: DateTime) (onBugFound : OnBugFound) = + let rec poll() = + async { + if token.IsCancellationRequested then + return () + else + let! _ = Async.AwaitWaitHandle(token.WaitHandle, int bugFoundPollInterval.TotalMilliseconds) + match RESTlerInternal.getRunExperimentFolder workingDirectory runStartTime with + | None -> + return! poll() + + | Some experiment -> + let bugBuckets = IO.DirectoryInfo(experiment.FullName ++ "bug_buckets") + let restlerExperimentLogs = experiment.FullName ++ "logs" + + if IO.Directory.Exists restlerExperimentLogs then + let bugsFoundPosted = restlerExperimentLogs ++ "raft-bugsfound.posted.txt" + let! postedBugs = + async { + if IO.File.Exists bugsFoundPosted then + let! bugsPosted = IO.File.ReadAllLinesAsync(bugsFoundPosted) |> Async.AwaitTask + return Set.ofArray bugsPosted + else + return Set.empty + } + + if bugBuckets.Exists then + let bugFiles = + bugBuckets.EnumerateFiles("*.txt") + |> Seq.filter isBugFile + |> Seq.map (fun f -> f.Name) + + let! _ = + bugFiles + |> Seq.map (fun bugFile -> + async { + if not <| postedBugs.Contains bugFile then + printfn "Posting bug found %s" bugFile + do! onBugFound {Experiment = experiment.Name; BugBucket = bugFile} + return () + } + ) |> Async.Sequential + + do! IO.File.WriteAllLinesAsync(bugsFoundPosted, bugFiles) |> Async.AwaitTask + + else + () + return! poll() + } + poll() + +let replay restlerRootDirectory workingDirectory replayLogFile (parameters: Raft.RESTlerTypes.Engine.EngineParameters) = + async { + let ts = DateTime.UtcNow + do! RESTlerInternal.replay restlerRootDirectory workingDirectory replayLogFile parameters + let! runSummary = processRunSummary workingDirectory ts + return runSummary + } + +let test (testType: string) + restlerRootDirectory workingDirectory + (parameters: Raft.RESTlerTypes.Engine.EngineParameters) + (onBugFound: OnBugFound) + (report: ReportRunSummary)(runStartTime: DateTime, reportInterval: TimeSpan option) = + async { + use token = new Threading.CancellationTokenSource() + let! _ = Async.Parallel [ + async { + do! RESTlerInternal.test testType restlerRootDirectory workingDirectory parameters + token.Cancel() + } + + resultAnalyzer workingDirectory token.Token report (runStartTime, reportInterval) + + pollForBugFound workingDirectory token.Token runStartTime onBugFound + + ] + return () + } + +let fuzz (fuzzType: string) + restlerRootDirectory + workingDirectory + (parameters: Raft.RESTlerTypes.Engine.EngineParameters) + (onBugFound : OnBugFound) + (report: ReportRunSummary) + (runStartTime: DateTime, reportInterval: TimeSpan option) = + async { + use token = new Threading.CancellationTokenSource() + let! _ = Async.Parallel [ + async { + do! RESTlerInternal.fuzz fuzzType restlerRootDirectory workingDirectory parameters + token.Cancel() + } + + resultAnalyzer workingDirectory token.Token report (runStartTime, reportInterval) + + pollForBugFound workingDirectory token.Token runStartTime onBugFound + ] + return () + } + diff --git a/src/Agent/RESTlerAgent/RESTlerTypes.fs b/src/Agent/RESTlerAgent/RESTlerTypes.fs new file mode 100644 index 0000000..36cc04d --- /dev/null +++ b/src/Agent/RESTlerAgent/RESTlerTypes.fs @@ -0,0 +1,303 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/// Copy paste of RESTler types consumed by the compiler and RESTler engine +module Raft.RESTlerTypes + +open System.Collections.Generic +module Engine = + + /// Options for refreshing an authentication token in the RESTler engine + type RefreshableTokenOptions = + { + /// The duration after which to refresh the token + refreshInterval : int + + /// The command that, when run, generates a new token in the form required + /// by the API (e.g. 'Header : ') + refreshCommand : string + } + + /// The user-facing engine parameters + type EngineParameters = + { + /// File path to the REST-ler (python) grammar. + grammarFilePath : string + + /// File path to the custom fuzzing dictionary. + mutationsFilePath : string + + /// The IP of the endpoint being fuzzed + targetIp : string + + /// The port of the endpoint being fuzzed + targetPort : int + + /// The maximum fuzzing time in hours + maxDurationHours : float option + + /// The authentication options, when tokens are required + refreshableTokenOptions : RefreshableTokenOptions option + + /// The delay in seconds after invoking an API that creates a new resource + producerTimingDelay : int + + /// Specifies to use SSL when connecting to the server + useSsl : bool + + /// The string to use in overriding the Host for each request + host : string option + + /// Path regex for filtering tested endpoints + pathRegex : string option + + /// The checker options + /// ["enable or disable", "list of specified checkers"] + checkerOptions : (string * string) list + } + + + type PerResourceSetting = + { + //seconds + producer_timing_delay: int + //use 1 + create_once: int + //path to custom dictionary + custom_dictionary : string + } + + type CheckerSettings = + { + mode : string + } + + type Settings = + { + max_combinations : int + //seconds + max_request_execution_time : int + + //seconds + global_producer_timing_delay : int + + //number of object of the same type before deleted by GC + dyn_object_cache_size : int + + //always 1 + fuzzing_jobs : int + + // available options: + // None <- used during Replay + // bfs; bfs-cheap; random-walk; directed-smoke-test + fuzzing_mode : string option + + // make it 30 seconds + garbage_collection_interval : int + + //false + ignore_dependencies: bool + + //false + ignore_feedback : bool + + //true + include_user_agent : bool + + //Number of seconds to wait for an asynchronous resource to be created before continuing (60 seconds ?) + max_async_resource_creation_time : int + + //100 + max_sequence_length : int + + //false + no_ssl : bool + //true + no_tokens_in_logs: bool + + path_regex : string option + + //The time, in milliseconds, to throttle each request being sent. + //This is here for special cases where the server will block requests from connections that arrive too quickly. + //Using this setting is not recommended + request_throttle_ms : int option + + //override host defined in swagger for every request + host: string option + + target_ip: string + + target_port : int + + //in hours + time_budget : float option + + token_refresh_cmd : string option + + //seconds + token_refresh_interval: int option + + //if set - poll for resource to be created before + //proceeding + wait_for_async_resource_creation : bool + + per_resource_settings : IDictionary option + + checkers : IDictionary option + } + + static member Default = + { + max_combinations = 20 + max_request_execution_time = 60 + + //seconds + global_producer_timing_delay = 3 + + //number of object of the same type before deleted by GC + dyn_object_cache_size = 100 + + //always 1 + fuzzing_jobs = 1 + + // available options: + // bfs; bfs-cheap; random-walk; directed-smoke-test + fuzzing_mode = Some "directed-smoke-test" + + // make it 30 seconds ? + garbage_collection_interval = 30 + + ignore_dependencies = false + ignore_feedback = false + include_user_agent = true + + //Number of seconds to wait for an asynchronous resource to be created before continuing (60 seconds ?) + max_async_resource_creation_time = 60 + + //100 + max_sequence_length = 100 + + //false + no_ssl = false + //true + no_tokens_in_logs = true + + path_regex = None + + request_throttle_ms = None + + host = None + + target_ip = "" + + target_port = 443 + + //in hours + time_budget = None + + token_refresh_cmd = None + + //seconds + token_refresh_interval = None + + //if set - poll for resource to be created before + //proceeding + wait_for_async_resource_creation = true + + per_resource_settings = None + + checkers = None + } + + static member FromEngineParameters (fuzzingMode: string option) (p : EngineParameters) = + let tokenRefreshInterval, tokenRefreshCommand = + match p.refreshableTokenOptions with + | None -> None, None + | Some options -> + (Some options.refreshInterval), (Some options.refreshCommand) + { + Settings.Default with + host = p.host + target_port = p.targetPort + target_ip = p.targetIp + time_budget = p.maxDurationHours + path_regex = p.pathRegex + global_producer_timing_delay = p.producerTimingDelay + no_ssl = not p.useSsl + fuzzing_mode = fuzzingMode + token_refresh_cmd = tokenRefreshCommand + token_refresh_interval = tokenRefreshInterval + } + + +/// Data structures consumed by RESTLer compiler, so we can convert parameters coming to the RAFT Agent and serialize them +/// to something that RESTler can work with +module Compiler = + /// User-specified compiler configuration + type Config = + { + swaggerSpecFilePath : string list option + + // If specified, use this as the input and generate the python grammar. + grammarInputFilePath : string option + + // If unspecified, will be set to the working directory + grammarOutputDirectoryPath : string option + + customDictionaryFilePath : string option + + // If specified, update the engine settings with hints derived from the grammar. + engineSettingsFilePath : string option + + includeOptionalParameters : bool + + useQueryExamples : bool + + useBodyExamples : bool + + /// When set to 'true', discovers examples and outputs them to a directory next to the grammar. + /// If an existing directory exists, does not over-write it. + discoverExamples : bool + + /// The directory where the compiler should look for examples. + /// If 'discoverExamples' is true, this directory will contain the + /// example files that have been discovered. + /// If 'discoverExamples' is false, every time an example is used in the + /// Swagger file, RESTler will first look for it in this directory. + examplesDirectory : string + + /// Perform payload body fuzzing + dataFuzzing : bool + + // When true, only fuzz the GET requests + readOnlyFuzz : bool + + resolveQueryDependencies: bool + + resolveBodyDependencies: bool + + useRefreshableToken : bool + + // When true, allow GET requests to be considered. + // This option is present for debugging, and should be + // set to 'false' by default. + // In limited cases when GET is a valid producer, the user + // should add an annotation for it. + allowGetProducers : bool + } + + type MutationsDictionary = + { + restler_fuzzable_string : string array + restler_fuzzable_int : string array + restler_fuzzable_number : string array + restler_fuzzable_bool : string array + restler_fuzzable_datetime : string array + restler_fuzzable_object : string array + restler_fuzzable_uuid4 : string array + restler_custom_payload : IDictionary option + restler_custom_payload_uuid4_suffix : IDictionary option + restler_custom_payload_header : IDictionary option + shadow_values : IDictionary> option + // TODO restler_multipart_formdata : Map option + } diff --git a/src/Agent/RESTlerAgent/RestlerAgent.fsproj b/src/Agent/RESTlerAgent/RestlerAgent.fsproj new file mode 100644 index 0000000..1212793 --- /dev/null +++ b/src/Agent/RESTlerAgent/RestlerAgent.fsproj @@ -0,0 +1,30 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Agent/RaftResultAnalyzer/RaftResultAnalyzer.fsproj b/src/Agent/RaftResultAnalyzer/RaftResultAnalyzer.fsproj new file mode 100644 index 0000000..df2dd84 --- /dev/null +++ b/src/Agent/RaftResultAnalyzer/RaftResultAnalyzer.fsproj @@ -0,0 +1,21 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + + + + + diff --git a/src/Agent/RaftResultAnalyzer/RaftResultAnalyzerMain.fs b/src/Agent/RaftResultAnalyzer/RaftResultAnalyzerMain.fs new file mode 100644 index 0000000..282b7f5 --- /dev/null +++ b/src/Agent/RaftResultAnalyzer/RaftResultAnalyzerMain.fs @@ -0,0 +1,276 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Learn more about F# at http://fsharp.org + +open System +open Microsoft.FSharpLu + +type System.Threading.Tasks.Task with + member x.ToAsync = Async.AwaitTask(x) + +type System.Threading.Tasks.Task<'T> with + member x.ToAsync = Async.AwaitTask(x) + +module CommandLineArguments = + type RunAnalyzerOn = + | RestlerNetworkLogPath of string + | RestlerResultsFolderPath of string + + type ResultAnalyzerArgs = + { + RunAnalyzerOn: RunAnalyzerOn option + BugBucketsPath : string option + } + + let [] ResultsFolderPath = "--restler-results-folder" + let [] NetworkLog = "--network-log-file-path" + let [] BugBuckets = "--bug-buckets" + + let usage = + [ + sprintf "RaftResultAnalyzer [%s | %s] %s" ResultsFolderPath NetworkLog BugBuckets + sprintf "%s " ResultsFolderPath + sprintf "%s " NetworkLog + sprintf "%s " BugBuckets + ] + |> (fun args -> String.Join("\n", args)) + + let parseCommandLine (argv: string array) = + if Array.isEmpty argv then + failwithf "Expected command line arguments %s" usage + else + let rec parse (config: ResultAnalyzerArgs) (args: string list) = + match args with + | [] -> config + | ResultsFolderPath :: path :: rest -> + parse {config with RunAnalyzerOn = Some (RunAnalyzerOn.RestlerResultsFolderPath path) } rest + | NetworkLog :: path :: rest -> + parse {config with RunAnalyzerOn = Some (RunAnalyzerOn.RestlerNetworkLogPath path) } rest + | BugBuckets :: path :: rest -> + parse {config with BugBucketsPath = Some (path)} rest + | arg :: _ -> failwithf "Unhandled command line parameter: %s" arg + parse {RunAnalyzerOn = None; BugBucketsPath = None} (argv |> List.ofArray) + + +let [] RaftAnalyzerFilePrefix = "raft-analyzer" + +type AnalyzerNetworkLogProgress = + { + NetworkLogName : string + FileProcessedOffset: int + + ResponseCodeCounts: Map + } + + static member Empty (logFileName : string) = + { + NetworkLogName = logFileName + FileProcessedOffset = 0 + ResponseCodeCounts = Map.empty + } + + +type SubArrayResult = + | SourceTooShort + | SubArrayFullMatch of int + | SubArrayPartialMatch of int + | NoMatch + +let inline subArrayMatch (srcAr: 'a array, srcStartPos: int, srcEndPos: int) (subAr: 'a array) = + if srcStartPos + subAr.Length > srcEndPos then + SourceTooShort + else + let mutable index = 0 + + while index < subAr.Length && srcAr.[srcStartPos + index] = subAr.[index] do + index <- index + 1 + + if index = 0 then + NoMatch + elif index = subAr.Length then + SubArrayFullMatch index + else + SubArrayPartialMatch index + + +let processBuffer (buffer: char array, bufferUsed: int) (snippet: char array) (state: 'a, onFullMatch: int -> 'a -> 'a) = + let rec doProcess (currentBufferIndex) (state: 'a) = + if currentBufferIndex >= bufferUsed then + state, currentBufferIndex + else + if buffer.[currentBufferIndex] = snippet.[0] then + match subArrayMatch (buffer, currentBufferIndex, bufferUsed) snippet with + | SubArrayFullMatch i -> + doProcess (currentBufferIndex + i) (onFullMatch (currentBufferIndex + i) state) + | SubArrayPartialMatch i -> + if currentBufferIndex + i + 1 >= bufferUsed then + // This is the end of the buffer and we got partial match. + // Let caller refill the buffer preserving the last section and then re-process the buffer + state, currentBufferIndex + else + doProcess (currentBufferIndex + i) state + | NoMatch -> + doProcess (currentBufferIndex + 1) state + | SourceTooShort -> + state, currentBufferIndex + else + doProcess (currentBufferIndex + 1) state + doProcess 0 state + + +let processRESTlerProgress (progressFilePath: string) = + let dateTimePrefixLen = "0000-00-00 00:00:00.000: ".Length + let receivedLogSnippet = @"Received: 'HTTP/1.1".ToCharArray() + async { + // logic goes as follows: find receivedLogSnippet, right after that the characters + // represent the response status code up to next space character + let bufferLen = 8 * 1024 * 1024 + let httpResponseCodeLength = 3 + let progressFile = IO.FileInfo(progressFilePath) + let progress : AnalyzerNetworkLogProgress = Json.Compact.deserializeFile progressFilePath + let logFile = IO.FileInfo (IO.Path.Join(progressFile.DirectoryName, progress.NetworkLogName)) + + if logFile.Length = int64 progress.FileProcessedOffset then + return progress + else + let fileStream = logFile.OpenText() + try + let buffer = Array.zeroCreate bufferLen + + let rec doProcess (progress: AnalyzerNetworkLogProgress) = + async { + fileStream.BaseStream.Seek(int64 progress.FileProcessedOffset, IO.SeekOrigin.Begin) |> ignore + let! bytesRead = fileStream.ReadAsync( buffer, 0, bufferLen).ToAsync + + let onBufferMatch bufferIndex (responseCodeCounts: Map) = + let isStartOfFile = (bufferIndex - receivedLogSnippet.Length - dateTimePrefixLen = 0) + let hasDelim = not isStartOfFile && (buffer.[bufferIndex - receivedLogSnippet.Length - dateTimePrefixLen - 1] = '\n') + let hasExpectedSpace = (buffer.[bufferIndex + httpResponseCodeLength + 1] = ' ') + + if (isStartOfFile || hasDelim) && hasExpectedSpace then + + let responseCode = String(buffer, bufferIndex, httpResponseCodeLength + 1) + match Int32.TryParse responseCode with + | true, n -> + if Map.containsKey n responseCodeCounts then + Map.add n (responseCodeCounts.[n] + 1) responseCodeCounts + else + Map.add n 1 responseCodeCounts + | false, _ -> + responseCodeCounts + else + responseCodeCounts + + let updatedCounts, newIndex = processBuffer (buffer, bytesRead) receivedLogSnippet (progress.ResponseCodeCounts, onBufferMatch) + + let updatedProgress = + { progress with + ResponseCodeCounts = updatedCounts + FileProcessedOffset = progress.FileProcessedOffset + newIndex + } + + Json.Compact.serializeToFile progressFilePath updatedProgress + + if bytesRead < bufferLen then + return updatedProgress + else + return! doProcess updatedProgress + } + return! doProcess progress + + finally + fileStream.Close() + } + +[] +let main argv = + + let config = CommandLineArguments.parseCommandLine argv + + let networkLogs, logDirectory = + match config.RunAnalyzerOn with + | None -> failwithf "Analyzer target is not set. %s" CommandLineArguments.usage + | Some (CommandLineArguments.RunAnalyzerOn.RestlerNetworkLogPath path) -> + let fi = IO.FileInfo path + if fi.Exists then + [|path|], fi.DirectoryName + else + failwithf "Could not find RESTler network log file: %s" path + | Some (CommandLineArguments.RunAnalyzerOn.RestlerResultsFolderPath folderPath) -> + if IO.Directory.Exists folderPath then + IO.Directory.GetFiles(folderPath, "network.*.txt", IO.SearchOption.TopDirectoryOnly), folderPath + else + eprintfn "Could not find RESTler logs folder: %s" folderPath + [||], folderPath + + let updateProgress = + networkLogs + |> Array.map (fun logPath -> + let logFileInfo = IO.FileInfo(logPath) + let progressFile = IO.FileInfo(IO.Path.Join(logFileInfo.DirectoryName, sprintf "%s.%s.json" RaftAnalyzerFilePrefix logFileInfo.Name)) + + if progressFile.Exists then + Json.Compact.deserializeFile progressFile.FullName + |> ignore + else + Json.Compact.serializeToFile progressFile.FullName (AnalyzerNetworkLogProgress.Empty logFileInfo.Name) + progressFile.FullName + ) + |> Array.map (fun progressFile -> + processRESTlerProgress progressFile + ) + |> Async.Sequential + |> Async.RunSynchronously + + let summary = + (Raft.JobEvents.RunSummary.Empty, updateProgress) + ||> Array.fold(fun s progress -> + let counts, total = + ((s.ResponseCodeCounts, s.TotalRequestCount), progress.ResponseCodeCounts) + ||> Map.fold(fun (summaryCounts, total) code count -> + if summaryCounts.ContainsKey code then + summaryCounts.Add(code, summaryCounts.[code] + count), total + count + else + summaryCounts.Add(code, count), total + count + ) + + { s with + ResponseCodeCounts = counts + TotalRequestCount = total + } + ) + + let summary = + let totalBuckets = "Total Buckets: " + let stopWhenHit = "-------------" + match config.BugBucketsPath with + | None -> + eprintfn "Bug buckets path is not set" + summary + | Some b -> + let bugBuckets = IO.FileInfo b + if bugBuckets.Exists then + let textStream = bugBuckets.OpenText() + try + let rec parseBugBuckets () = + let line = textStream.ReadLine() + if line.StartsWith stopWhenHit then + summary + else if line.StartsWith(totalBuckets) then + match Int32.TryParse (line.Substring(totalBuckets.Length)) with + | true, n -> {summary with TotalBugBucketsCount = n} + | false, _ -> summary + else + parseBugBuckets() + + parseBugBuckets() + + finally + textStream.Close() + else + summary + + if IO.Directory.Exists logDirectory then + Json.Compact.serializeToFile (IO.Path.Join(logDirectory, (sprintf "%s-summary.json" RaftAnalyzerFilePrefix))) summary + 0 diff --git a/src/Contracts/AppInsights.fs b/src/Contracts/AppInsights.fs new file mode 100644 index 0000000..21c60e7 --- /dev/null +++ b/src/Contracts/AppInsights.fs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft.Controllers.AppInsights + + +open Microsoft.ApplicationInsights +open Microsoft.AspNetCore.Http + +type Log (client: TelemetryClient) = + let convertTagsToProperties tags = + tags |> Map.ofList|> Map.toSeq |> dict + member this.Info message tags = client.TrackTrace(message, DataContracts.SeverityLevel.Information, convertTagsToProperties tags) + member this.Warning message tags = client.TrackTrace(message, DataContracts.SeverityLevel.Warning, convertTagsToProperties tags) + member this.Error message tags = client.TrackTrace(message, DataContracts.SeverityLevel.Error, convertTagsToProperties tags) + member this.Event name tags = client.TrackEvent(name, convertTagsToProperties tags) + member this.Metric (name:string) value = + let metric = client.GetMetric(name) + metric.TrackValue(value) + member this.Exception ex tags = client.TrackException(ex, convertTagsToProperties tags) + diff --git a/src/Contracts/Errors.fs b/src/Contracts/Errors.fs new file mode 100644 index 0000000..ce0ec51 --- /dev/null +++ b/src/Contracts/Errors.fs @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft + +open System.Runtime.Serialization +open System.Net + +module Errors = + + // The api guidelines https://github.com/Microsoft/api-guidelines/blob/vNext/Guidelines.md + // recommends that a standard structure be used for returning errors. These types define that + // standard structure. + // The structure will be deserialized into json and returned in the error response body. + + // These error codes must remain stable. Adding/Subtracting forces a new version of the api. + [] + type ApiErrorCode = + | [] InvalidTag = 0 + | [] QueryStringMissing = 1 + | [] QueryStringInvalid = 2 + | [] MissingHeader = 3 + | [] InternalError = 4 + | [] InvalidJob = 5 + | [] NoJobsFound = 6 + | [] ParseError = 7 + | [] NotFound = 8 + + + /// Inner error can be used for cascading exception handlers or where there are field validations + /// and multiple errors need to be returned. + [] + type InnerError = + { + /// Inner detailed message + [] + Message : string + } + + [] + type ApiErrors = + { + /// The main error encountered + [] + Code : ApiErrorCode + + /// A detail string that can be used for debugging + [] + Message : string + + /// Function name that generated the error + [] + Target : string + + /// An array of details about specific errors that led to this reported error. + [] + Details : ApiErrors[] + + /// An object containing more specific information than the current object about the error. + [] + InnerError : InnerError + + } + + /// The guidelines specify that the top level structure has only this one member. + [] + type ApiError = + { + /// Main field for errors. + [] + Error : ApiErrors + } + + /// Catch ApiErrors from the request + exception ApiErrorException of ApiError with + override this.Message = + sprintf "%A" this + + let raiseApiError (apiError:ApiError) = + ApiErrorException(apiError) + |> raise diff --git a/src/Contracts/Job.fs b/src/Contracts/Job.fs new file mode 100644 index 0000000..3c69416 --- /dev/null +++ b/src/Contracts/Job.fs @@ -0,0 +1,155 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft.Job + +module Authentication = + + // TODO: add support for "https://graph.windows.net" (right now only "https://management.core.windows.net/" is supported + type AzureADConfig = + { + (* Path to a file with the following format. + { + "applications": [ + { + "name": "Service Principal Name", + "authentication_endpoint": "https://login.microsoftonline.com/", + "application_id": "1234abcd-123a-456b-789d-123abc4567de", + "application_tenant_id": "1234abcd-123a-456b-789d-123abc4567de" + } + ] + } + *) + + SettingsFilePath: string + + (* + Path to a file with the following format: + { + "Service Principal Name": "Service principal secret" + } + *) + + SecretsFilePath : string + } + + type TokenRefresh = + | CommandLine of string + | MSAL of string + | TxtToken of string + +type SwaggerLocation = + // URL to a swagger definition + | URL of string + // This can be a path to a file from a mounted file share + | FilePath of string + + +type RaftTask = + { + ToolName: string + + IsIdling: bool + /// Output folder name to store agent generated output + OutputFolder : string + + /// overwrite where to get swagger definition from + SwaggerLocation : SwaggerLocation + + /// The string to use in overriding the Host for each request + Host : string option + + /// Duration of the job; if not set, then job runs till completion + Duration: System.TimeSpan option + + //list of names of secrets in Keyvault that payload allowed to access + KeyVaultSecrets : string array option + + AuthenticationMethod : Authentication.TokenRefresh option + + ToolConfiguration : Newtonsoft.Json.Linq.JObject + } + + +type FileShareMount = + { + FileShareName : string //any fileShare name from the service storage account + MountPath : string //example "/my-job-config" + } + +type Resources = + { + Cores : int + MemoryGBs : int + } + +type Webhook = + { + Name : string + Metadata : Map + } + + +type JobDefinition = + { + /// where to get swagger definition from + SwaggerLocation : SwaggerLocation + + /// prefix for jobId + NamePrefix : string option + + /// root file share to use to write job results + /// instead of creating new file share per each job run + RootFileShare : string option + + Resources : Resources + + // !!NOTE!!: according to Azure Container spec, we can have up to 60 elements in this array + Tasks : RaftTask array + + /// Duration of the job; if not set, then job runs till completion + Duration: System.TimeSpan option + + /// The string to use in overriding the Host for each request + Host : string option + + /// Name of the webhook + Webhook : Webhook option + + // File shares to mount from RAFT deployment storage account. + // Use case: RESTler compiles swagger as a job run + // To use the output from the compile step - mount the file share produced + // by compile step, and use grammar from that step to run fuzz step + // !!NOTE!!: according to Azure spec we can have up-to 19 elements in this list (since we reserve 1 to mount as working directory) + ReadOnlyFileShareMounts : (FileShareMount array) option + + ReadWriteFileShareMounts : (FileShareMount array) option + } + + +type CreateJobRequest = + { + IsIdlingRun : bool + + Region : string option + + JobId : string + + JobDefinition: JobDefinition + } + +type DeleteJobRequest = + { + JobId : string + } + +// We need some way of designating that these types are returned to the customer +// public? external? ReturnedJobId? +// We have types we consume and types we return to the customer. What is the best +// naming convention? +type CreateJobResponse = + { + JobId : string + } + + diff --git a/src/Contracts/JobEvents.fs b/src/Contracts/JobEvents.fs new file mode 100644 index 0000000..33e1d56 --- /dev/null +++ b/src/Contracts/JobEvents.fs @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +module Raft.JobEvents + +open System + +type JobState = + | Creating + | Created + | Running + | Completed + | ManuallyStopped + | Error + | TimedOut + +/// Returns True if s1 state has higher precedence than s2 +/// False otherwise +let ( ??> ) (s1: JobState) (s2: JobState) = + match s1, s2 with + | JobState.Creating, _ -> false + + | JobState.Created, JobState.Creating -> true + | JobState.Created, _ -> false + + | JobState.Running, (JobState.Creating | JobState.Created) -> true + | JobState.Running, _ -> false + + | JobState.ManuallyStopped, (JobState.Creating | JobState.Created | JobState.Running | JobState.Completed | JobState.Error) -> true + | JobState.ManuallyStopped, _ -> false + + | JobState.Completed , (JobState.Error | JobState.Completed) -> false + | (JobState.Completed | JobState.TimedOut | JobState.Error), _ -> true + +type RunSummary = + { + TotalRequestCount: int + ResponseCodeCounts: Map + TotalBugBucketsCount: int + } + + static member Empty = + { + TotalBugBucketsCount = 0 + TotalRequestCount = 0 + ResponseCodeCounts = Map.empty + } + + +module Events = + + type JobEventTypes = + | JobStatus + | BugFound + + +type JobStatus = + { + Tool: string + JobId : string + State: JobState + Metrics: RunSummary option + UtcEventTime: DateTime + Details: string seq option + Metadata : Map option + AgentName: string + } + + static member EventType = Events.JobEventTypes.JobStatus.ToString() + + +type RESTlerBugDetails = + { + Experiment : string + BugBucket : string + } + +type 'a BugFound = + { + Tool : string + JobId: string + AgentName : string + Metadata : Map option + BugDetails : 'a + } + + static member EventType = Events.JobEventTypes.BugFound.ToString() \ No newline at end of file diff --git a/src/Contracts/StorageEntities.fs b/src/Contracts/StorageEntities.fs new file mode 100644 index 0000000..bd439bb --- /dev/null +++ b/src/Contracts/StorageEntities.fs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +module Raft.StorageEntities + +open Microsoft.Azure.Cosmos.Table + +let JobStatusTableName = "JobStatus" +type JobStatusEntity(jobId, agentName, jobStatus) = + inherit TableEntity(partitionKey=jobId, rowKey=agentName) + new() = JobStatusEntity(null, null, null) + member val JobStatus : string = jobStatus with get, set + + +let JobTableName = "Job" +type JobEntity(jobId, webhook) = + inherit TableEntity(partitionKey=jobId, rowKey=jobId) + new() = JobEntity(null, null) + member val Webhook : string = webhook with get, set + + +let JobWebHookTableName = "JobWebhook" +type JobWebhookEntity(jobId, webhookName) = + inherit TableEntity(partitionKey=jobId, rowKey=webhookName) + new() = JobWebhookEntity(null, null) diff --git a/src/Contracts/Telemetry.fs b/src/Contracts/Telemetry.fs new file mode 100644 index 0000000..b999c98 --- /dev/null +++ b/src/Contracts/Telemetry.fs @@ -0,0 +1,177 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft.Telemetry + +open System +open Microsoft.ApplicationInsights +open System.Reflection +open Microsoft.ApplicationInsights.Metrics + +// The installation is a hash of the subscription Id and the deployment name. +type InstallationHash = string + +// The version here is the version of the api +type Version = string + +// the name that implements a route api +type RoutePath = string + +// Type of REST method used +type HTTPMethod = string + +// in the event of an exception, capture the stack trace. +type FailureStackTrace = string +type MethodName = string +type HttpStatus = int + +// Telemetry collected about the RESTler tool +// This data is used to improve the service. The information is anonymous. + +type TelemetryValues = + | ContainerGroupAverageCPUUsage of float * DateTime + | ContainerGroupAverageRAMUsageMB of float * DateTime + | JobFuzzingDurationRequest of float // Requested fuzzing duration + | AverageNetworkBytesTransmittedPerSecond of float * DateTime // per job - I think these per/job metrics are only interesting on a job basis. + | AverageNetworkBytesReceivedPerSecond of float * DateTime // per job + | ApiRequest of MethodName * float + | Exception of exn + | GCRun of float * int * int // time took to run GC in seconds + + | Created of string * DateTime //tool name * eventTimeStamp + | Deleted of string * DateTime //tool name * eventTimeStamp + | Completed of string * DateTime //tool name * bugs found * eventTimeStamp + | Error of string * DateTime // tool name * eventTimeStamp + | TimedOut of string * DateTime //tool name * eventTimeStamp + | BugsFound of int * string * DateTime //number of bugs * tool name + | StatusCount of HttpStatus * int * string * DateTime // http status code * count * tool name * eventTimeStamp + + | Tasks of (string * int) array * int // (payload name * how many payloads with the name) array * total payloads overall + +module Central = + module private Namespaces = + let [] Jobs = "Jobs" + let [] Containers = "Containers" + let [] GarbageCollection = "GarbageCollection" + module private Labels = + let [] SiteHash = "SiteHash" + let [] Version = "Version" + let [] TimeStamp = "TimeStamp" + let [] Units = "Units" + let [] Name = "Name" + let [] Total = "Total" + let [] ToolName = "ToolName" + + type TelemetryImpl(telemetryConfig: (TelemetryClient * string) option) = + let convertTagsToProperties tags = tags |> dict + let version = Assembly.GetEntryAssembly().GetName().Version + + member _.TelemetryConfig = telemetryConfig + + member _.ConvertTagsToProperties tags = convertTagsToProperties tags + + member _.TrackError (telemetryValue:TelemetryValues) = + // The telemetry client value can be null during unit testing. We don't want to pollute the + // our metrics with unit tests. + match telemetryConfig with + | Some (telemetry, siteHash) -> + let properties = convertTagsToProperties [Labels.SiteHash, siteHash; Labels.Version, version.ToString()] + match telemetryValue with + | Exception ex -> + telemetry.TrackException(ex, properties) + | _ -> () // Only exceptions are allowed to be tracked with this telemetry type + | None -> () + + member __.TrackMetric (telemetryValue:TelemetryValues, units: string) = + // The telemetry client value can be null during unit testing. We don't want to pollute the + // our metrics with unit tests. + match telemetryConfig with + | Some (telemetry, site) -> + match telemetryValue with + | ContainerGroupAverageCPUUsage (cpu, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Containers, "CPUUsage", Labels.Units, Labels.SiteHash, Labels.TimeStamp, Labels.Version)) + m.TrackValue(float cpu, units, site, timeStamp.ToString(), version.ToString()) |> ignore + + | ContainerGroupAverageRAMUsageMB (ram, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Containers, "RamUsage", Labels.Units, Labels.SiteHash, Labels.TimeStamp, Labels.Version)) + m.TrackValue(ram, units, site, timeStamp.ToString(), version.ToString()) |> ignore + + | JobFuzzingDurationRequest time -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, "Duration", Labels.Units, Labels.SiteHash, Labels.Version)) + m.TrackValue(time, units, site, version.ToString()) |> ignore + + | AverageNetworkBytesTransmittedPerSecond (bytes, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Containers, "AverageNetworkBytesTransmittedPerSecond", Labels.Units, Labels.SiteHash, Labels.TimeStamp, Labels.Version)) + m.TrackValue(bytes, units, site, timeStamp.ToString(), version.ToString()) |> ignore + + | AverageNetworkBytesReceivedPerSecond (bytes, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Containers, "AverageNetworkBytesReceivedPerSecond", Labels.Units, Labels.SiteHash, Labels.TimeStamp, Labels.Version)) + m.TrackValue(bytes, units, site, timeStamp.ToString(), version.ToString()) |> ignore + + | GCRun(duration, successfulDeletions, failedDeletions) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.GarbageCollection, "GCRun", Labels.Units, Labels.SiteHash, Labels.Version)) + m.TrackValue(duration, units, site, version.ToString()) |> ignore + + let m1 = telemetry.GetMetric(MetricIdentifier(Namespaces.GarbageCollection, "SuccessfulDeletions", Labels.Units, Labels.SiteHash, Labels.Version)) + m1.TrackValue(float successfulDeletions, units, site, version.ToString()) |> ignore + + let m2 = telemetry.GetMetric(MetricIdentifier(Namespaces.GarbageCollection, "FailedDeletions", Labels.Units, Labels.SiteHash, Labels.Version)) + m2.TrackValue(float failedDeletions, units, site, version.ToString()) |> ignore + + | Created (name, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, "Created", Labels.Units, Labels.Name, Labels.TimeStamp, Labels.SiteHash, Labels.Version)) + m.TrackValue(1.0, units, name, timeStamp.ToString(), site, version.ToString()) |> ignore + + | Deleted (name, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, "Deleted", Labels.Units, Labels.Name, Labels.TimeStamp, Labels.SiteHash, Labels.Version)) + m.TrackValue(1.0, units, name, timeStamp.ToString(), site, version.ToString()) |> ignore + + | Tasks(tasks, total) -> + let mTotal = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, "TotalPayloads", Labels.Units, Labels.SiteHash, Labels.Version)) + mTotal.TrackValue(float total, units, site, version.ToString()) |> ignore + + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, "Payloads", Labels.Units, Labels.Name, Labels.Total, Labels.SiteHash, Labels.Version)) + tasks + |> Array.iter(fun (name, count) -> + m.TrackValue(float count, units, name, total.ToString(), site, version.ToString()) |> ignore + ) + + let mPercentage = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, "Payloads %", Labels.Units, Labels.Name, Labels.Total, Labels.SiteHash, Labels.Version)) + tasks + |> Array.iter(fun (name, count) -> + mPercentage.TrackValue( 100.0 * (float count) / (float total), "%", name, total.ToString(), site, version.ToString()) |> ignore + ) + + | Completed (name, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, "Completed", Labels.Units, Labels.Name, Labels.TimeStamp, Labels.SiteHash, Labels.Version)) + m.TrackValue(1.0, units, name, timeStamp.ToString(), site, version.ToString()) |> ignore + + | BugsFound(bugsFound, toolName, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, "BugsFound", Labels.Units, Labels.ToolName, Labels.TimeStamp, Labels.SiteHash, Labels.Version)) + m.TrackValue(float bugsFound, units, toolName, timeStamp.ToString(), site, version.ToString()) |> ignore + + | StatusCount(statusCode, count, toolName, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, sprintf "%A" statusCode, Labels.Units, Labels.ToolName, Labels.TimeStamp, Labels.SiteHash, Labels.Version)) + m.TrackValue(float count, units, toolName, timeStamp.ToString(), site, version.ToString()) |> ignore + + | Error (name, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, "Error", Labels.Units, Labels.Name, Labels.TimeStamp, Labels.SiteHash, Labels.Version)) + m.TrackValue(1.0, units, name, timeStamp.ToString(), site, version.ToString()) |> ignore + + | TimedOut(name, timeStamp) -> + let m = telemetry.GetMetric(MetricIdentifier(Namespaces.Jobs, "TimedOut", Labels.Units, Labels.Name, Labels.TimeStamp, Labels.SiteHash, Labels.Version)) + m.TrackValue(1.0, units, name, timeStamp.ToString(), site, version.ToString()) |> ignore + + | Exception _ -> + // This should not be logged with TrackMetric, just ignore. + () + | v -> + __.TrackError(Exception (exn(sprintf "Unhandled telemetry metric %A" v))) + | None -> + () + + let mutable Telemetry = TelemetryImpl(None) + + let Initialize client siteHash = + Telemetry <- TelemetryImpl(Some(client, siteHash)) + true \ No newline at end of file diff --git a/src/Contracts/VersionedContract.fs b/src/Contracts/VersionedContract.fs new file mode 100644 index 0000000..ccdf79f --- /dev/null +++ b/src/Contracts/VersionedContract.fs @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +module Raft.Message + +open Newtonsoft +open Newtonsoft.Json +open Microsoft.FSharpLu + +module ServiceBus = + module Queue = + let [] create = "raft-jobcreate" + let [] delete = "raft-jobdelete" + + module Topic = + let [] events = "raft-jobevents" + + +module InternalHelpers = + type TupleAsArraySettings = + static member formatting = Newtonsoft.Json.Formatting.Indented + static member settings = + JsonSerializerSettings( + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore, + Converters = [| Microsoft.FSharpLu.Json.CompactUnionJsonConverter(true, true) |] + ) + type private J = Microsoft.FSharpLu.Json.With + + type EventType = + { + EventType : string + } + + let getEventType (msg: string) : string = + (J.deserialize msg).EventType + + +module RaftEvent = + + type RaftJobEvent< ^T when ^T : (static member EventType : string) > = + { + EventType : string + Message: ^T + } + + let inline createJobEvent (message : ^T when ^T : (static member EventType : string)) = + { + EventType = ( ^T : (static member EventType : string)()) // call static EventType getter + Message = message + } + + let inline serializeToJson (msg : RaftJobEvent< ^T >) = + Json.Compact.serialize msg + + let inline serializeToBytes (msg: RaftJobEvent< ^T >) = + msg |> serializeToJson |> System.Text.Encoding.UTF8.GetBytes + + let inline deserializeJson (json: string) = + Json.Compact.deserialize< RaftJobEvent< ^T > > json + + let inline deserializeBytes (bytes: byte array) = + bytes |> System.Text.Encoding.UTF8.GetString |> deserializeJson + + let inline tryDeserializeJson (json: string) = + Json.Compact.tryDeserialize< RaftJobEvent< ^T > > json + + let getEventType (msg: string) : string = InternalHelpers.getEventType msg + + let inline deserializeEvent (message: string) = + deserializeJson message + + let inline tryDeserializeEvent (message: string) = + tryDeserializeJson message + +module RaftCommand = + + type RaftCommand< 'T > = + { + Message: 'T + MessagePostCount : int + } + + let createCommand (message : 'T) = + { + MessagePostCount = 0 + Message = message + } + + let inline serializeToJson (msg : RaftCommand<'T>) = + Json.Compact.serialize msg + + let inline serializeToBytes (msg: RaftCommand<'T>) = + msg |> serializeToJson |> System.Text.Encoding.UTF8.GetBytes + + let inline deserializeJson (json: string) = + Json.Compact.deserialize< RaftCommand<_> > json + + let inline deserializeBytes (bytes: byte array) = + bytes |> System.Text.Encoding.UTF8.GetString |> deserializeJson + + let inline deserializeCommand (message: string) = + deserializeJson message + + + +type MetricType = + | ContainerConsumedResources + | JobStatus + | CreateJob + | JobService + | CustomerService + | OperatorService + +type RaftMetricMessage< 'T > = + { + metricType: MetricType + message: 'T + } + + static member SerializeToJson (msg : RaftMetricMessage<'T>) = + Json.Compact.serialize msg + + static member SerializeToBytes (msg: RaftMetricMessage<'T>) = + msg |> RaftMetricMessage.SerializeToJson |> System.Text.Encoding.UTF8.GetBytes + + member this.SerializeToBytes () = RaftMetricMessage<_>.SerializeToBytes this \ No newline at end of file diff --git a/src/Contracts/Webhooks.fs b/src/Contracts/Webhooks.fs new file mode 100644 index 0000000..69e920f --- /dev/null +++ b/src/Contracts/Webhooks.fs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Raft.Webhooks + +open System +open System.Collections.Generic + + +type JobStateWebHook = + { + State : string + } +type BugFoundWebHook = + { + JobId : string + } + +// This is the type that is used to create webhooks and to report +// webhooks. +type WebHook = + { + WebhookName : string + Event : string + TargetUrl : Uri + } + + +type WebHookEnvelope<'T> = + { + Topic: string + Id: string + EventType: string + Subject: string + EventTime: string + Data: 'T + DataVersion : string + } + +type SentEvent = + { + Event : string + Status : string + } + + \ No newline at end of file diff --git a/src/Orchestrator/Dockerfile b/src/Orchestrator/Dockerfile new file mode 100644 index 0000000..0951f0a --- /dev/null +++ b/src/Orchestrator/Dockerfile @@ -0,0 +1,10 @@ +# IMPORTANT NOTE: List of all function-docker images can be found here +# https://hub.docker.com/_/microsoft-azure-functions-dotnet +# See FULL TAG LISTING at the bottom of the page for list of available images and versions + +FROM mcr.microsoft.com/azure-functions/dotnet:3.0 + +ENV AzureWebJobsScriptRoot=/home/site/wwwroot \ + AzureFunctionsJobHost__Logging__Console__IsEnabled=true + +COPY . /home/site/wwwroot diff --git a/src/Orchestrator/Orchestrator.sln b/src/Orchestrator/Orchestrator.sln new file mode 100644 index 0000000..a3c0ba2 --- /dev/null +++ b/src/Orchestrator/Orchestrator.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29806.167 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orchestrator", "Orchestrator\Orchestrator.csproj", "{6B48556D-1871-4E4B-95BA-1D800B478E5A}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "OrchestratorLogic", "OrchestratorLogic\OrchestratorLogic.fsproj", "{0C0D3007-1939-496A-92FF-5B077ACA5E9B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6B48556D-1871-4E4B-95BA-1D800B478E5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B48556D-1871-4E4B-95BA-1D800B478E5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B48556D-1871-4E4B-95BA-1D800B478E5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B48556D-1871-4E4B-95BA-1D800B478E5A}.Release|Any CPU.Build.0 = Release|Any CPU + {0C0D3007-1939-496A-92FF-5B077ACA5E9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C0D3007-1939-496A-92FF-5B077ACA5E9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C0D3007-1939-496A-92FF-5B077ACA5E9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C0D3007-1939-496A-92FF-5B077ACA5E9B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2B3080E4-E865-4BA1-960C-C27ADCAFACC3} + EndGlobalSection +EndGlobal diff --git a/src/Orchestrator/Orchestrator/Orchestrator.cs b/src/Orchestrator/Orchestrator/Orchestrator.cs new file mode 100644 index 0000000..6c029a7 --- /dev/null +++ b/src/Orchestrator/Orchestrator/Orchestrator.cs @@ -0,0 +1,194 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Threading.Tasks; +using Microsoft.ApplicationInsights; +using Microsoft.Extensions.Logging; +using Microsoft.Azure.ServiceBus.Core; +using Microsoft.Azure.WebJobs; +using Microsoft.Azure.ServiceBus; +using Microsoft.Azure.Management.Fluent; +using Microsoft.Azure.Management.ResourceManager.Fluent; +using Microsoft.Azure.Cosmos.Table; +using System.Collections.Generic; +using Microsoft.Azure.Management.AppService.Fluent.Models; +using Microsoft.Azure.Management.Monitor.Fluent.Models; + +namespace OrchestratorFunc +{ + public static class Orchestrator + { + private static String GetSetting(String envVariableName) + { + return Environment.GetEnvironmentVariable(envVariableName, EnvironmentVariableTarget.Process); + } + + private static OrchestratorLogic.ContainerInstances.AgentConfig agentConfig; + private static OrchestratorLogic.ContainerInstances.CommunicationClients communicationClients; + private static IDictionary, string>> toolConfigs; + + private static IEnumerable> dockerConfigs; + private static IDictionary secrets; + + private static IAzure Authenticate() { + var credentials = + new Microsoft.Azure.Management.ResourceManager.Fluent.Authentication.AzureCredentialsFactory() + .FromServicePrincipal( + GetSetting("RAFT_SERVICE_PRINCIPAL_CLIENT_ID"), + GetSetting("RAFT_SERVICE_PRINCIPAL_CLIENT_SECRET"), + GetSetting("RAFT_SERVICE_PRINCIPAL_TENANT_ID"), AzureEnvironment.AzureGlobalCloud); + + var azure = Microsoft.Azure.Management.Fluent.Azure + .Configure() + .Authenticate(credentials) + .WithSubscription(GetSetting("RAFT_SERVICE_PRINCIPAL_SUBSCRIPTION_ID")); + return azure; + } + + private static async Task CreateDefaultTables() { + CloudStorageAccount storageAccount = CloudStorageAccount.Parse(GetSetting("RAFT_STORAGE_TABLE_CONNECTION_STRING")); + CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); + CloudTable table = tableClient.GetTableReference("WebhooksTriggerTest"); + var result = await table.CreateIfNotExistsAsync(); + + table = tableClient.GetTableReference(Raft.StorageEntities.JobStatusTableName); + result = await table.CreateIfNotExistsAsync(); + + table = tableClient.GetTableReference(Raft.StorageEntities.JobTableName); + result = await table.CreateIfNotExistsAsync(); + + table = tableClient.GetTableReference(Raft.StorageEntities.JobWebHookTableName); + result = await table.CreateIfNotExistsAsync(); + } + + private static IAzure azure = Authenticate(); + + static Orchestrator() + { + try + { + var resourceGroup = GetSetting("RAFT_CONTAINER_RUN_RESOURCE_GROUP"); + var storageAccount = GetSetting("RAFT_ORCHESTRATOR_STORAGE"); + var storageAccountKey = OrchestratorLogic.ContainerInstances.getStorageKeyTask(azure, resourceGroup, storageAccount); + storageAccountKey.Wait(); + + var utilsStorageAccount = GetSetting("RAFT_UTILS_STORAGE"); + var utilsStorageAccountKey = OrchestratorLogic.ContainerInstances.getStorageKeyTask(azure, resourceGroup, utilsStorageAccount); + utilsStorageAccountKey.Wait(); + + var resultsStorageAccount = GetSetting("RAFT_RESULTS_STORAGE"); + var resultsStorageAccountKey = OrchestratorLogic.ContainerInstances.getStorageKeyTask(azure, resourceGroup, resultsStorageAccount); + resultsStorageAccountKey.Wait(); + + + var metricsKey = GetSetting("RAFT_METRICS_APP_INSIGHTS_KEY"); + var aiKey = GetSetting("RAFT_APPINSIGHTS"); + + agentConfig = new OrchestratorLogic.ContainerInstances.AgentConfig( + resourceGroup: resourceGroup, + storageAccount: storageAccount, + storageAccountKey: storageAccountKey.Result, + keyVault: GetSetting("RAFT_KEY_VAULT"), + appInsightsKey: aiKey, + outputSas: GetSetting("RAFT_SERVICEBUS_AGENT_SEND_EVENTS_CONNECTION_STRING"), + storageTableConnectionString: GetSetting("RAFT_STORAGE_TABLE_CONNECTION_STRING"), + eventGridEndpoint: GetSetting("RAFT_EVENT_GRID_ENDPOINT"), + eventGridKey: GetSetting("RAFT_EVENT_GRID_KEY"), + siteHash: GetSetting("RAFT_SITE_HASH"), + + utilsStorageAccount: utilsStorageAccount, + utilsStorageAccountKey: utilsStorageAccountKey.Result, + utilsFileShare: GetSetting("RAFT_UTILS_FILESHARE"), + resultsStorageAccount: resultsStorageAccount, + resultsStorageAccountKey: resultsStorageAccountKey.Result + ); + + var allSecrets = OrchestratorLogic.ContainerInstances.initializeSecretsFromKeyvault(azure, agentConfig); + allSecrets.Wait(); + + secrets = allSecrets.Result.Item1; + dockerConfigs = allSecrets.Result.Item2; + + communicationClients = + new OrchestratorLogic.ContainerInstances.CommunicationClients( + jobEventsSender: new MessageSender(GetSetting("RAFT_REPORT_JOB_STATUS"), Raft.Message.ServiceBus.Topic.events, RetryPolicy.Default), + jobCreationSender: new MessageSender(GetSetting("RAFT_REPORT_JOB_STATUS"), Raft.Message.ServiceBus.Queue.create, RetryPolicy.Default), + webhookSender: new System.Net.Http.HttpClient() + ); + + //Initialize shared dependencies here + Raft.Telemetry.Central.Initialize(new TelemetryClient(new Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration(metricsKey)), agentConfig.SiteHash); + + var createTables = CreateDefaultTables(); + createTables.Wait(); + + var tools = OrchestratorLogic.ContainerInstances.initializeTools(agentConfig); + tools.Wait(); + toolConfigs = tools.Result; + } + catch (Exception ex) { + Raft.Telemetry.Central.Telemetry.TrackError(Raft.Telemetry.TelemetryValues.NewException(ex)); + throw; + } + } + + [FunctionName(Raft.Message.ServiceBus.Queue.create)] + public static async Task CreateJob([ServiceBusTrigger(Raft.Message.ServiceBus.Queue.create, IsSessionsEnabled = true)] string createJobMessage, ILogger log) + { + await OrchestratorLogic.ContainerInstances.createJob( + log, + secrets, + dockerConfigs, + toolConfigs, + azure, + agentConfig, + communicationClients, + createJobMessage); + } + + [FunctionName(Raft.Message.ServiceBus.Queue.delete)] + public static async Task Delete([ServiceBusTrigger(Raft.Message.ServiceBus.Queue.delete, IsSessionsEnabled = true)]string deleteJobMessage, ILogger log) + { + await OrchestratorLogic.ContainerInstances.delete( + log, + azure, + agentConfig, + communicationClients, + deleteJobMessage); + } + + + [FunctionName("jobstatus-handler")] + public static async Task Status([ServiceBusTrigger(Raft.Message.ServiceBus.Topic.events, "jobstatus-handler")]string statusMessage, ILogger log) + { + await OrchestratorLogic.ContainerInstances.status( + log, + azure, + agentConfig, + communicationClients, + statusMessage); + } + + [FunctionName("webhooks-handler")] + public static async Task WebhookMessage([ServiceBusTrigger(Raft.Message.ServiceBus.Topic.events, "webhooks-handler")] string webhookMessage, ILogger log) + { + await OrchestratorLogic.ContainerInstances.webhookMessage( + log, + azure, + agentConfig, + communicationClients, + webhookMessage); + } + + [FunctionName("raft-timer-garbage-collection")] + public static async Task TimerGarbageCollection([TimerTrigger("0 */1 * * * *")] TimerInfo t, ILogger log) + { + await OrchestratorLogic.ContainerInstances.gc( + log, + azure, + agentConfig, + communicationClients); + } + } +} diff --git a/src/Orchestrator/Orchestrator/Orchestrator.csproj b/src/Orchestrator/Orchestrator/Orchestrator.csproj new file mode 100644 index 0000000..fee0223 --- /dev/null +++ b/src/Orchestrator/Orchestrator/Orchestrator.csproj @@ -0,0 +1,26 @@ + + + netcoreapp3.1 + v3 + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + \ No newline at end of file diff --git a/src/Orchestrator/Orchestrator/host.json b/src/Orchestrator/Orchestrator/host.json new file mode 100644 index 0000000..b9f92c0 --- /dev/null +++ b/src/Orchestrator/Orchestrator/host.json @@ -0,0 +1,3 @@ +{ + "version": "2.0" +} \ No newline at end of file diff --git a/src/Orchestrator/OrchestratorLogic/Dockerfile b/src/Orchestrator/OrchestratorLogic/Dockerfile new file mode 100644 index 0000000..889b61e --- /dev/null +++ b/src/Orchestrator/OrchestratorLogic/Dockerfile @@ -0,0 +1,12 @@ +# IMPORTANT NOTE: List of all function-docker images can be found here +# https://hub.docker.com/_/microsoft-azure-functions-base +# https://mcr.microsoft.com/v2/azure-functions/base/tags/list + +# To enable ssh & remote debugging on app service change the base image to the one below +# FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appservice +FROM mcr.microsoft.com/azure-functions/dotnet:3.0 + +ENV AzureWebJobsScriptRoot=/home/site/wwwroot \ + AzureFunctionsJobHost__Logging__Console__IsEnabled=true + +COPY . /home/site/wwwroot diff --git a/src/Orchestrator/OrchestratorLogic/Orchestrator.fs b/src/Orchestrator/OrchestratorLogic/Orchestrator.fs new file mode 100644 index 0000000..b109199 --- /dev/null +++ b/src/Orchestrator/OrchestratorLogic/Orchestrator.fs @@ -0,0 +1,1444 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace OrchestratorLogic + +open System +open Raft.Message +open Microsoft.Azure +open Microsoft.Azure.Management.ContainerInstance.Fluent +open Microsoft.Azure.Management.ResourceManager.Fluent +open Microsoft.Azure.Management.Fluent +open Microsoft.Extensions.Logging +open Microsoft.Azure.Cosmos.Table +open Raft.JobEvents +open Raft.StorageEntities +open Raft.Webhooks +open Raft.Telemetry +open Raft.Job +open System.Net +open System.Collections.Generic + +module ContainerInstances = + module Tags = + let [] Duration = "duration" + let [] StartTimeUtc = "startTimeUTC" + //user can change this tag to True if they want to prevent + //garbage collection from deleting the container group + let [] GCReady = "gcReady" + + // if set to true, then this container group is used for re-running + // multiple runs of commands + let [] IsIdling = "isIdling" + + let getFromTags (tryParse: string -> bool * 'a) (tags: IReadOnlyDictionary) (tag: string) = + match tags.TryGetValue tag with + | true, v -> + match tryParse v with + | true, b -> Some b + | false, _ -> None + | false, _ -> None + + let inline getBoolFromTags tags tag = getFromTags Boolean.TryParse tags tag + let inline getDateTimeFromTags tags tag = getFromTags DateTime.TryParse tags tag + let inline getTimeSpanFromTags tags tag = getFromTags TimeSpan.TryParse tags tag + + let isGcReady (tags: Collections.Generic.IReadOnlyDictionary) = + match getBoolFromTags tags GCReady with + | Some true | None -> true + | Some false -> false + + let isIdling (tags: Collections.Generic.IReadOnlyDictionary) = + match getBoolFromTags tags IsIdling with + | Some true -> true + | None | Some false -> false + + let getStartTime (tags: Collections.Generic.IReadOnlyDictionary) = + getDateTimeFromTags tags StartTimeUtc + + let getDuration (tags: Collections.Generic.IReadOnlyDictionary) = + getTimeSpanFromTags tags Duration + + type System.Threading.Tasks.Task with + member x.ToAsync = Async.AwaitTask(x) + + type System.Threading.Tasks.Task<'T> with + member x.ToAsync = Async.AwaitTask(x) + + module Exceptions = + let exnOfType< 't when 't :> exn > (f: 't -> bool) (e : exn) = + match e with + | :? 't as ex when f ex -> Some ex + | :? System.AggregateException as ex when + (ex.InnerException :? 't && f (ex.InnerException :?> 't)) -> + Some (ex.InnerException :?> 't) + | _ -> None + + let (|AlreadyExists|_|) (e : exn) = + exnOfType (fun ex -> ex.Status = int Net.HttpStatusCode.Conflict) e + + + type AgentConfig = + { + ResourceGroup: string + StorageAccount: string + StorageAccountKey: string + KeyVault: string + AppInsightsKey: string + OutputSas: string + StorageTableConnectionString: string + + SiteHash: string + EventGridEndpoint: string + EventGridKey: string + UtilsStorageAccount: string + UtilsStorageAccountKey: string + UtilsFileShare: string + + ResultsStorageAccount : string + ResultsStorageAccountKey: string + } + + type DockerConfig = + { + Repository: string + User: string + Password: string + } + + type CommunicationClients = + { + JobEventsSender: ServiceBus.Core.MessageSender + JobCreationSender : ServiceBus.Core.MessageSender + WebhookSender : System.Net.Http.HttpClient + } + + let containerGroupName (jobId: string) = jobId + + let createJobStatus (jobId: string) (state: JobState) (details: string list option) = + let message: JobStatus = + { + AgentName = jobId.ToString() + Tool = "" + JobId = jobId + State = state + Metrics = None + UtcEventTime = System.DateTime.UtcNow + Details = (match details with None -> None | Some d -> Some (Seq.ofList d)) + Metadata = None + } + Raft.Message.RaftEvent.createJobEvent message + + let postStatus (jobStatusSender: ServiceBus.Core.MessageSender) (jobId: string) (state: JobState) (details: string list option) = + async { + let jobStatus = createJobStatus jobId state details + do! jobStatusSender.SendAsync( + ServiceBus.Message ( RaftEvent.serializeToBytes jobStatus ) + ).ToAsync + } + + let rePostJobCreate (jobCreateSender: ServiceBus.Core.MessageSender) (jobCreateMessage : RaftCommand.RaftCommand) = + async { + let rePostDelay = TimeSpan.FromSeconds(10.0) + let message = ServiceBus.Message (RaftCommand.serializeToBytes {jobCreateMessage with MessagePostCount = jobCreateMessage.MessagePostCount + 1}) + message.SessionId <- jobCreateMessage.Message.JobId.ToString() + let! _ = jobCreateSender.ScheduleMessageAsync( + message, (DateTimeOffset.UtcNow + rePostDelay)).ToAsync + () + } + + type ToolConfiguration = + { + Tool: string + Container: string + + RunDirectory : string + IsIdling : bool + + Command : string + CommandArguments: string array + + IdleCommand : string + IdleCommandArguments: string array + + Secrets : string array option + } + + type ContainerToolRun = + { + ContainerName : string + RunDirectory : string + WorkDirectory : string + ToolConfiguration: ToolConfiguration + } + + + type ToolCommand = + { + Command : string + Arguments: string array + } + + type GpuConfig = + { + Sku : string //available SKUs v100, k80, P100 + Cores : int + } + type ContainerConfig = + { + CPUs : int option + MemorySizeInGB : float option + GPUs : GpuConfig option + } + + type ToolConfig = + { + Container : string + + Run : ToolCommand + Idle : ToolCommand + } + + let getStorageKey (azure: IAzure) (resourceGroup: string, storageAccount: string) = + async { + let! storage = azure.StorageAccounts.GetByResourceGroupAsync(resourceGroup, storageAccount).ToAsync + let! keys = storage.GetKeysAsync().ToAsync + let storageKey = keys.[0].Value + return storageKey + } + + let getStorageKeyTask (azure: IAzure) (resourceGroup: string, storageAccount: string) = + getStorageKey azure (resourceGroup, storageAccount) |> Async.StartAsTask + + let initializeTools (agentConfig: AgentConfig) = + async { + let auth = Microsoft.Azure.Storage.Auth.StorageCredentials(agentConfig.UtilsStorageAccount, agentConfig.UtilsStorageAccountKey;) + let account = Microsoft.Azure.Storage.CloudStorageAccount(auth, true) + let sasUrl = account.ToString(true) + + let directoryClient = Azure.Storage.Files.Shares.ShareDirectoryClient(sasUrl, agentConfig.UtilsFileShare, "tools") + + let asyncEnum = directoryClient.GetFilesAndDirectoriesAsync().GetAsyncEnumerator() + + let rec loadAllConfigs(allConfigs) = + async { + let! next = asyncEnum.MoveNextAsync().AsTask().ToAsync + if next then + if asyncEnum.Current.IsDirectory then + try + let fileClient = directoryClient.GetSubdirectoryClient(asyncEnum.Current.Name).GetFileClient("config.json") + let! file = fileClient.DownloadAsync().ToAsync + let toolConfig : ToolConfig = Microsoft.FSharpLu.Json.Compact.deserializeStream(file.Value.Content) + return! loadAllConfigs ((asyncEnum.Current.Name, Result.Ok((sprintf "/raft-utils/tools/%s" asyncEnum.Current.Name), toolConfig)) :: allConfigs) + with ex -> + return! loadAllConfigs ((asyncEnum.Current.Name, Result.Error(ex.Message)) :: allConfigs) + else + return! loadAllConfigs allConfigs + else + return allConfigs + } + + let! configs = loadAllConfigs [] + return dict configs + } |> Async.StartAsTask + + + let initializeSecretsFromKeyvault (azure: IAzure) (agentConfig: AgentConfig) = + async { + let! keyVault = azure.Vaults.GetByResourceGroupAsync(agentConfig.ResourceGroup, agentConfig.KeyVault).ToAsync + let! secrets = keyVault.Secrets.ListAsync(true) |> Async.AwaitTask + let secretNames = + let e = secrets.GetEnumerator() + [ + while e.MoveNext() do + yield e.Current.Name.ToLower() + ] + + let! secretTuples = + secretNames + |> List.map (fun name -> + async { + let! s= keyVault.Secrets.GetByNameAsync(name) |> Async.AwaitTask + return name, s.Value + } + ) + |> Async.Sequential + + let secrets = secretTuples |> dict + + let privateRegistries = + secrets + |> Seq.filter(fun (KeyValue(k, _)) -> + k.ToLower().StartsWith("privateregistry") + ) + |> Seq.map (fun (KeyValue(k, v)) -> + (k.ToLower()), ((v |> Microsoft.FSharpLu.Json.Compact.deserialize) : DockerConfig) + ) + return secrets, privateRegistries + } |> Async.StartAsTask + + let getToolConfiguration + (dockerConfigs: (string*DockerConfig) seq) + (toolsConfigs : IDictionary>) + (task: RaftTask) = + async { + match toolsConfigs.TryGetValue(task.ToolName) with + | true, Result.Ok(runDirectory, c) -> + let container = + dockerConfigs + |> Seq.tryPick( fun (k, v) -> + let t = sprintf"{%s}" k + if c.Container.Contains(t, StringComparison.OrdinalIgnoreCase) then + Some (c.Container.Replace(t, v.Repository, StringComparison.OrdinalIgnoreCase)) + else + None + ) + |> Option.defaultValue c.Container + + return + { + Tool = task.ToolName + RunDirectory = runDirectory + Container = container + + Secrets = task.KeyVaultSecrets + IsIdling = task.IsIdling + IdleCommand = c.Idle.Command + IdleCommandArguments = c.Idle.Arguments + + Command = c.Run.Command + CommandArguments = c.Run.Arguments + } + | true, Result.Error(err) -> + return failwithf "Cannot get %s tool configuration: %s" task.ToolName err + + | false, _ -> + return failwithf "Failed to get configuration for unsupported tool: %A" task.ToolName + } + + let createJobShareAndFolders (logger: ILogger) (containerGroupName: string) (sasUrl: string) (jobCreateRequest: CreateJobRequest) = + async { + let shareName, createSubDirectory, shareQuota = + match jobCreateRequest.JobDefinition.RootFileShare with + | None -> + let shareQuota = 1 + containerGroupName, (fun _ -> async {return ""}), shareQuota + | Some rootFileShare -> + let shareQuota = 1000 + rootFileShare, + (fun (shareClient:Azure.Storage.Files.Shares.ShareClient) -> + async { + let d = sprintf "%s/" containerGroupName + let directoryClient = shareClient.GetDirectoryClient(d) + let! _ = directoryClient.CreateIfNotExistsAsync().ToAsync + return d + }), + shareQuota + + let logInfo format = Printf.kprintf logger.LogInformation format + logInfo "Creating config fileshare: %s" shareName + + let saveString(fileName: string) (data: string) = + async { + let file = Azure.Storage.Files.Shares.ShareFileClient(sasUrl, shareName, fileName) + let! _ = file.DeleteIfExistsAsync().ToAsync + + let! _ = file.CreateAsync(int64 data.Length).ToAsync + + use fileWriter = new IO.MemoryStream(Text.Encoding.UTF8.GetBytes(data)) + let! _ = file.UploadAsync(fileWriter).ToAsync + let! _ = fileWriter.FlushAsync().ToAsync + return () + } + + let shareClient = Azure.Storage.Files.Shares.ShareClient(sasUrl, shareName) + let! _ = shareClient.CreateIfNotExistsAsync(dict[], Nullable(shareQuota)).ToAsync + + let! subDirectory = createSubDirectory(shareClient) + + + do! saveString (sprintf "%sjob-config.json" subDirectory) (Microsoft.FSharpLu.Json.Compact.Strict.serialize jobCreateRequest) + + let! tasksConfigurations = + jobCreateRequest.JobDefinition.Tasks + |> Array.mapi(fun index task -> + async { + let taskDirectory = sprintf "%s%s" subDirectory task.OutputFolder + + let directoryClient = shareClient.GetDirectoryClient(taskDirectory) + let! _ = directoryClient.CreateIfNotExistsAsync().ToAsync + do! saveString (sprintf "%s/%s" taskDirectory "task-config.json") (Microsoft.FSharpLu.Json.Compact.Strict.serialize task) + return index, taskDirectory, task + } + ) + |> Async.Sequential + return shareName, tasksConfigurations + } + + module RaftContainerGroup = + + let mountShare (cg: ContainerGroup.Definition.IWithVolume) (storageAccountName: string, storageAccountKey: string) (mounts: FileShareMount array option, isReadOnly: bool) = + match mounts with + | Some shares -> + (cg, shares) + ||> Array.fold(fun a fs -> + let withShares = + let v = a.DefineVolume(fs.FileShareName) + if isReadOnly then + v.WithExistingReadOnlyAzureFileShare(fs.FileShareName) + else + v.WithExistingReadWriteAzureFileShare(fs.FileShareName) + withShares + .WithStorageAccountName(storageAccountName) + .WithStorageAccountKey(storageAccountKey) + .Attach() + ) + | None -> cg + + + let configureContainerInstances + (cg: ContainerGroup.Definition.IWithVolume) (resources: Resources) + (toolContainerRunsWithSecrets: (ContainerToolRun * IDictionary * IDictionary) array) + (workDirectory, workVolume) (readOnlyShares, readWriteShares) = + + let numberOfTasks = Array.length toolContainerRunsWithSecrets + let cores = float resources.Cores + let mem = float resources.MemoryGBs + + let cpu = System.Math.Round(cores / float numberOfTasks, 2, MidpointRounding.ToZero) + let ram = System.Math.Round(mem / float numberOfTasks, 1, MidpointRounding.ToZero) + + let r, isIdling, _ = + ((Choice1Of2(cg), false, (cores, mem)), toolContainerRunsWithSecrets) + ||> Array.fold (fun (a, isIdling, (remainingCpu, remainingRam)) (toolContainerRun, secrets, environmentVariables) -> + let cpu = + if remainingCpu >= 0.01 && remainingCpu < cpu then + System.Math.Round(remainingCpu, 2, MidpointRounding.ToZero) + else + cpu + + let ram = + if remainingRam >= 0.1 && remainingRam < ram then + System.Math.Round(remainingRam, 1, MidpointRounding.ToZero) + else + ram + + let c = + let b = + match a with + | Choice1Of2 b -> + b.DefineContainerInstance toolContainerRun.ContainerName + | Choice2Of2 (b: ContainerGroup.Definition.IWithNextContainerInstance) -> + b.DefineContainerInstance toolContainerRun.ContainerName + + b + .WithImage(toolContainerRun.ToolConfiguration.Container) + .WithoutPorts() + .WithCpuCoreCount(cpu) + .WithMemorySizeInGB(ram) + .WithVolumeMountSetting(workVolume, workDirectory) + + let d = + match readOnlyShares with + | Some shares -> + (c, shares) + ||> Array.fold (fun s fs -> + s.WithReadOnlyVolumeMountSetting(fs.FileShareName, fs.MountPath) + ) + | None -> c + + let e = + match readWriteShares with + | Some shares -> + (d, shares) + ||> Array.fold (fun s fs -> + s.WithVolumeMountSetting(fs.FileShareName, fs.MountPath) + ) + | None -> d + + let f = e.WithEnvironmentVariablesWithSecuredValue secrets + let g = f.WithEnvironmentVariables environmentVariables + + let cmd, args = + if toolContainerRun.ToolConfiguration.IsIdling then + toolContainerRun.ToolConfiguration.IdleCommand, toolContainerRun.ToolConfiguration.IdleCommandArguments + else + toolContainerRun.ToolConfiguration.Command, toolContainerRun.ToolConfiguration.CommandArguments + + Choice2Of2(g.WithStartingCommandLine(cmd, args).Attach()), + (isIdling || toolContainerRun.ToolConfiguration.IsIdling), + (remainingCpu - cpu, remainingRam - ram) + ) + r, isIdling + + let getContainerGroupInstanceConfiguration + (containerGroupName: string) + (logger:ILogger) + (agentConfig: AgentConfig) + (dockerConfigs: (string * DockerConfig) seq) + (toolsConfigs : IDictionary>) + (jobCreateRequest: Raft.Job.CreateJobRequest) = + async { + let workVolume = jobCreateRequest.JobId + let workDirectory = sprintf "/work-directory-%s" jobCreateRequest.JobId + + let auth = Microsoft.Azure.Storage.Auth.StorageCredentials(agentConfig.ResultsStorageAccount, agentConfig.ResultsStorageAccountKey) + let account = Microsoft.Azure.Storage.CloudStorageAccount(auth, true) + let sasUrl = account.ToString(true) + + let makeToolConfig payload = + getToolConfiguration dockerConfigs toolsConfigs payload + + let! shareName, tasksConfigurations = createJobShareAndFolders logger containerGroupName sasUrl jobCreateRequest + + tasksConfigurations + |> Array.countBy(fun (_, _, task) -> task.ToolName) + |> (fun tasks -> + Central.Telemetry.TrackMetric(TelemetryValues.Tasks(tasks, tasksConfigurations.Length), "N") + ) + + let! containerToolRuns = + tasksConfigurations + |> Array.map (fun (i, taskDirectory, task) -> + async { + let! toolConfig = makeToolConfig task + return + { + RunDirectory = toolConfig.RunDirectory + WorkDirectory = sprintf "%s/%s" workDirectory taskDirectory + ContainerName = (sprintf "%d-%s" i task.OutputFolder).ToLowerInvariant() + ToolConfiguration = toolConfig + } + } + ) + |> Async.Sequential + return containerToolRuns, shareName, workVolume, workDirectory + } + + let getContainerRunCommandString command (commandArguments: string array) = + let commandArgumentsString = + commandArguments + |> Array.map(fun s -> sprintf "\"%s\"" (s.Replace("\"", "\\\""))) + |> (fun args -> String.Join(" ", args)) + + sprintf "%s %s" command commandArgumentsString + + let runDebugContainers + (existingContainerGroup : IContainerGroup) + (logger:ILogger) + (agentConfig: AgentConfig) + (dockerConfigs: (string * DockerConfig) seq) + (toolsConfigs : IDictionary>) + (jobCreateRequest: Raft.Job.CreateJobRequest) = + async { + let logInfo format = Printf.kprintf logger.LogInformation format + let! containerToolRunsConfigurations, _, _, _ = getContainerGroupInstanceConfiguration existingContainerGroup.Name logger agentConfig dockerConfigs toolsConfigs jobCreateRequest + let! _ = + containerToolRunsConfigurations + |> Array.filter (fun toolRunConfig -> toolRunConfig.ToolConfiguration.IsIdling) + |> Array.map (fun toolRunConfig -> + async { + let cmd = getContainerRunCommandString toolRunConfig.ToolConfiguration.Command toolRunConfig.ToolConfiguration.CommandArguments + logInfo "Since isIdling is set: on %s in %s running %s" toolRunConfig.ContainerName existingContainerGroup.Name cmd + + let! runCmd = + existingContainerGroup.ExecuteCommandAsync(toolRunConfig.ContainerName, toolRunConfig.ToolConfiguration.IdleCommand, 80, 40).ToAsync + + use websocketsClient = new System.Net.WebSockets.ClientWebSocket() + do! websocketsClient.ConnectAsync(System.Uri(runCmd.WebSocketUri), Async.DefaultCancellationToken).ToAsync + + let send (s: string) = + websocketsClient.SendAsync( ArraySegment(System.Text.Encoding.UTF8.GetBytes(s)), + System.Net.WebSockets.WebSocketMessageType.Text, + true, + Async.DefaultCancellationToken).ToAsync + + let sendCommand (s: string) = send (s + "\r\n") + + do! send runCmd.Password + do! sendCommand cmd + do! sendCommand "exit" + + do! websocketsClient.CloseAsync(Net.WebSockets.WebSocketCloseStatus.NormalClosure, "Debug session completed", Async.DefaultCancellationToken).ToAsync + return () + } + ) |> Async.Sequential + () + } + + + let createContainerGroupInstance + (containerGroupName: string) + (logger:ILogger) + (azure: IAzure) + (secrets : IDictionary) + (agentConfig: AgentConfig) + (dockerConfigs: (string * DockerConfig) seq, toolsConfigs : IDictionary>) + (jobCreateRequest: Raft.Job.CreateJobRequest) + (reportDeploymentError : exn -> Async) + = + async { + let logInfo format = Printf.kprintf logger.LogInformation format + try + if Array.isEmpty jobCreateRequest.JobDefinition.Tasks then + return failwithf "No tasks defined for the job: %A" jobCreateRequest.JobId + else + logInfo "Creating container group for job: %A" jobCreateRequest.JobId + let resourceGroup = azure.ResourceGroups.GetByName(agentConfig.ResourceGroup) + let! containerToolRunsConfigurations, shareName, workVolume, workDirectory = + getContainerGroupInstanceConfiguration containerGroupName logger agentConfig dockerConfigs toolsConfigs jobCreateRequest + + logInfo "Deploying container group: %s for job : %A" containerGroupName jobCreateRequest.JobId + + let region = resourceGroup.Region + logInfo "Container group does not exist %s. Deploying..." containerGroupName + + let _1_1 = + azure + .ContainerGroups + .Define(containerGroupName) + .WithRegion(match jobCreateRequest.Region with None -> region | Some r -> Core.Region.Create(r)) + .WithExistingResourceGroup(agentConfig.ResourceGroup) + .WithLinux() + + let _1_2 = + if Seq.isEmpty dockerConfigs then + _1_1.WithPublicImageRegistryOnly() + else + let h = snd (Seq.head dockerConfigs) + (_1_1.WithPrivateImageRegistry(h.Repository, h.User, h.Password), Seq.tail dockerConfigs) + ||> Seq.fold(fun a (_, v) -> + a.WithPrivateImageRegistry(v.Repository, v.User, v.Password) + ) + + let _1 = + _1_2.DefineVolume(workVolume) + .WithExistingReadWriteAzureFileShare(shareName) + .WithStorageAccountName(agentConfig.ResultsStorageAccount) + .WithStorageAccountKey(agentConfig.ResultsStorageAccountKey) + .Attach() + + logInfo "Mounting read-only fileshares %s : %A" containerGroupName jobCreateRequest.JobDefinition.ReadOnlyFileShareMounts + let _2_1 = RaftContainerGroup.mountShare _1 + (agentConfig.ResultsStorageAccount, agentConfig.ResultsStorageAccountKey) + (jobCreateRequest.JobDefinition.ReadOnlyFileShareMounts, true) + + let utilsFileShares = [| { FileShareName = agentConfig.UtilsFileShare; MountPath = "/raft-utils" } |] + let _2 = RaftContainerGroup.mountShare _2_1 + (agentConfig.UtilsStorageAccount, agentConfig.UtilsStorageAccountKey) + ((Some utilsFileShares), true) + + logInfo "Mounting read-write fileshares %s : %A" containerGroupName jobCreateRequest.JobDefinition.ReadWriteFileShareMounts + let _3 = RaftContainerGroup.mountShare _2 + (agentConfig.ResultsStorageAccount, agentConfig.ResultsStorageAccountKey) + (jobCreateRequest.JobDefinition.ReadWriteFileShareMounts, false) + + let getSecret (name: string) = + match secrets.TryGetValue(name.ToLower()) with + | true, v -> v + | false, _ -> + failwithf "Secret with name %s does not exist" name + + let! containerToolRunsConfigurationsWithSecrets = + containerToolRunsConfigurations + |> Array.mapi(fun i config -> + async { + let! secrets = + match config.ToolConfiguration.Secrets with + | Some toolSecrets -> + toolSecrets + |> Array.map(fun secretName -> + async { + let secret = getSecret secretName + //add prefix in order to avoid overriding existing + //environment variables on the image + return sprintf "RAFT_%s" secretName, secret + } + ) + |> Async.Sequential + | None -> async.Return [||] + + let predefinedEnvironmentVariablesDict = + dict [| + "RAFT_JOB_ID", jobCreateRequest.JobId + "RAFT_TASK_INDEX", sprintf "%d" i + "RAFT_CONTAINER_GROUP_NAME", containerGroupName + "RAFT_CONTAINER_NAME", config.ContainerName + "RAFT_APP_INSIGHTS_KEY", agentConfig.AppInsightsKey + "RAFT_WORK_DIRECTORY", config.WorkDirectory + "RAFT_RUN_DIRECTORY", config.RunDirectory + "RAFT_RUN_CMD", getContainerRunCommandString config.ToolConfiguration.Command config.ToolConfiguration.CommandArguments + |] + + let secretsDict = dict (Array.append secrets [|"RAFT_SB_OUT_SAS", agentConfig.OutputSas|]) + return config, secretsDict, predefinedEnvironmentVariablesDict + } + ) + |> Async.Sequential + + + let readOnlyFileShares = + Some( + Array.append + (Option.defaultWith (fun () -> Array.empty) jobCreateRequest.JobDefinition.ReadOnlyFileShareMounts) + utilsFileShares + ) + + let _4 = RaftContainerGroup.configureContainerInstances + _3 jobCreateRequest.JobDefinition.Resources + containerToolRunsConfigurationsWithSecrets + (workDirectory, workVolume) + (readOnlyFileShares, jobCreateRequest.JobDefinition.ReadWriteFileShareMounts) + + match _4 with + | Choice1Of2 (_), _ -> + return failwithf "No container instances configured for container group: %s" containerGroupName + + | Choice2Of2(w), isIdling -> + logInfo "Finishing deployment %s: (isIdling: %A)" containerGroupName isIdling + let newTags = + let tags = + // if job is created for debugging, then it has no duration and does not expire + match jobCreateRequest.JobDefinition.Duration, isIdling with + | Some d, false -> Map.empty.Add(Tags.Duration, sprintf "%A" d) + | None, (true | false) | Some _, true -> Map.empty + + tags + .Add(Tags.StartTimeUtc, sprintf "%A" System.DateTime.UtcNow) + .Add(Tags.GCReady, sprintf "%A" false) + .Add(Tags.IsIdling, sprintf "%A" isIdling) + + async { + logInfo "Starting background creation of :%s with tags: %A" containerGroupName newTags + try + let! _ = + w + .WithTags(newTags) + .WithRestartPolicy(Models.ContainerGroupRestartPolicy.Never) + .CreateAsync() + .ToAsync + () + with + | ex -> + do! reportDeploymentError ex + } + |> Async.Start + + logInfo "Started deployment of %s" containerGroupName + return Result.Ok () + with + | ex -> + return Result.Error (ex) + } + + let getJobStatusTable connectionString = + async { + let tableName = Raft.StorageEntities.JobStatusTableName + let storageAccount = CloudStorageAccount.Parse(connectionString) + let tableClient = storageAccount.CreateCloudTableClient() + let table = tableClient.GetTableReference(tableName) + return table + } + + let getWebHookTable connectionString = + async { + let tableName = Raft.StorageEntities.JobWebHookTableName + let storageAccount = CloudStorageAccount.Parse(connectionString) + let tableClient = storageAccount.CreateCloudTableClient() + let table = tableClient.GetTableReference(tableName) + return table + } + + let getJobTable connectionString = + async { + let tableName = Raft.StorageEntities.JobTableName + let storageAccount = CloudStorageAccount.Parse(connectionString) + let tableClient = storageAccount.CreateCloudTableClient() + let table = tableClient.GetTableReference(tableName) + return table + } + + module ContainerGroupStates = + let [] Stopped = "Stopped" + let [] Running = "Running" + let [] Pending = "Pending" + let [] Succeeded = "Succeeded" + let [] Failed = "Failed" + + + let createJob + (logger:ILogger) + (secrets : IDictionary) + (dockerConfigs: (string * DockerConfig) seq, toolsConfigs: IDictionary>, + azure: IAzure, agentConfig: AgentConfig, communicationClients: CommunicationClients) + (message: string) = + async { + let logInfo format = Printf.kprintf logger.LogInformation format + let logError format = Printf.kprintf logger.LogError format + + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + + logInfo "Got queue message: %s" message + let decodedMessage: RaftCommand.RaftCommand = RaftCommand.deserializeCommand message + + let postStatus = postStatus communicationClients.JobEventsSender decodedMessage.Message.JobId + + let containerGroupName = containerGroupName decodedMessage.Message.JobId + + let! existingContainerGroupOpt = + async { + let! cg = azure.ContainerGroups.GetByResourceGroupAsync(agentConfig.ResourceGroup, containerGroupName).ToAsync + return Option.ofObj cg + } + + let reportDeploymentError (ex: Exception) = + async { + match ex with + | :? System.AggregateException as ag -> + match ag.InnerException with + | :? Microsoft.Rest.Azure.CloudException as ce + when (ce.Response.StatusCode = Net.HttpStatusCode.NotFound || ce.Response.StatusCode = Net.HttpStatusCode.OK || + ce.Response.StatusCode = Net.HttpStatusCode.TooManyRequests)-> + // ignore this exception. This is caused due to azure SDK waiting for azure success return after container + // creation finished. Meanwhile container group execution terminated already and garbage collection deleted the container group. + // azure SDK throws this failure. + () + | :? Microsoft.Rest.Azure.CloudException as ce -> + // it looks like the error when container group is transitioning states is OK to ignore. Need to get more info on that. + logError "Failed to deploy container group %s due to %A (status code : %A)" containerGroupName ex ce.Response.StatusCode + do! postStatus JobState.Error (Some [ex.Message]) + + | _ -> + logError "Failed to deploy container group %s due to %A" containerGroupName ex + do! postStatus JobState.Error (Some [ex.Message]) + | _ -> + logError "Failed to deploy container group %s due to %A" containerGroupName ex + do! postStatus JobState.Error (Some [ex.Message]) + } + + match existingContainerGroupOpt with + | None -> + let! table = getJobStatusTable agentConfig.StorageTableConnectionString + let retrieve = TableOperation.Retrieve(decodedMessage.Message.JobId.ToString(), decodedMessage.Message.JobId.ToString()) + let! retrieveResult = table.ExecuteAsync(retrieve).ToAsync + + let isError = + if retrieveResult.HttpStatusCode = int HttpStatusCode.OK then + let r = retrieveResult.Result :?> JobStatusEntity + let currentRow: RaftEvent.RaftJobEvent = RaftEvent.deserializeEvent r.JobStatus + currentRow.Message.State = JobState.Error + else + false + + if decodedMessage.MessagePostCount > 0 && isError then + logInfo "Message for job %A will not be reposted initial container group creation did not succeed" decodedMessage.Message.JobId + else + do! postStatus JobState.Creating None + match! createContainerGroupInstance containerGroupName logger azure secrets agentConfig (dockerConfigs, toolsConfigs) decodedMessage.Message reportDeploymentError with + | Result.Ok () -> + //this is newly created container. Poll until it is fully running and then update job status + do! rePostJobCreate communicationClients.JobCreationSender decodedMessage + + stopWatch.Stop() + logInfo "Time took to start job deployment: %s total seconds %f" containerGroupName stopWatch.Elapsed.TotalSeconds + + | Result.Error (ex) -> + stopWatch.Stop() + logError "Failed to create container group for job : %A due to %A (Time it took: %f total seconds)" decodedMessage.Message.JobId ex stopWatch.Elapsed.TotalSeconds + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + do! postStatus JobState.Error (Some [ex.Message]) + + | Some existingContainerGroup -> + match Option.ofObj existingContainerGroup.State with + | Some state -> + match state with + | ContainerGroupStates.Running | ContainerGroupStates.Succeeded | ContainerGroupStates.Stopped | ContainerGroupStates.Failed -> + stopWatch.Stop() + logInfo "Time took to deploy job: %s total seconds %f. State: %s; Provisioning State : %s" + containerGroupName stopWatch.Elapsed.TotalSeconds state existingContainerGroup.ProvisioningState + do! postStatus JobState.Created None + + if decodedMessage.Message.IsIdlingRun then + do! runDebugContainers existingContainerGroup logger agentConfig dockerConfigs toolsConfigs decodedMessage.Message + else + let! _ = existingContainerGroup.Update().WithTag(Tags.GCReady, sprintf "%A" true).ApplyAsync().ToAsync + () + + | ContainerGroupStates.Pending | null -> + do! rePostJobCreate communicationClients.JobCreationSender decodedMessage + + | state -> + logError "Unhandled container instance %s state: %s" containerGroupName state + do! rePostJobCreate communicationClients.JobCreationSender decodedMessage + | None -> + do! rePostJobCreate communicationClients.JobCreationSender decodedMessage + + return () + } |> Async.StartAsTask + + + let stopJob (containerGroup: IContainerGroup) = + async { + let! _ = containerGroup.Update().WithTag(Tags.GCReady, sprintf "%A" true).ApplyAsync().ToAsync + do! containerGroup.StopAsync().ToAsync + } + + let delete (logger:ILogger) (azure: IAzure, agentConfig: AgentConfig, communicationClients: CommunicationClients) (message: string) = + async { + let logInfo format = Printf.kprintf logger.LogInformation format + let logError format = Printf.kprintf logger.LogError format + + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + + let decodedMessage: RaftCommand.RaftCommand = RaftCommand.deserializeCommand message + logInfo "Got delete queue message: %A" decodedMessage + + let postStatus = postStatus communicationClients.JobEventsSender decodedMessage.Message.JobId + + let containerGroupName = containerGroupName decodedMessage.Message.JobId + + let! containerGroup = azure.ContainerGroups.GetByResourceGroupAsync(agentConfig.ResourceGroup, containerGroupName).ToAsync + + do! stopJob containerGroup + do! postStatus JobState.Completed None + stopWatch.Stop() + logInfo "Time took to stop job: %s total seconds %f" containerGroupName stopWatch.Elapsed.TotalSeconds + + return () + } |> Async.StartAsTask + + + let status (logger:ILogger) (_, agentConfig: AgentConfig, communicationClients: CommunicationClients) (message: string) = + async { + let logInfo format = Printf.kprintf logger.LogInformation format + let logError format = Printf.kprintf logger.LogError format + + logInfo "[STATUS] Got status message: %s" message + + let eventType = RaftEvent.getEventType message + if eventType = BugFound<_>.EventType then + () + else if eventType = JobStatus.EventType then + let decodedMessage: RaftEvent.RaftJobEvent = RaftEvent.deserializeEvent message + + let! table = getJobStatusTable agentConfig.StorageTableConnectionString + let retrieve = TableOperation.Retrieve(decodedMessage.Message.JobId.ToString(), decodedMessage.Message.AgentName) + let! retrieveResult = table.ExecuteAsync(retrieve).ToAsync + + let currentStatusWithHigherPrecedence = + if retrieveResult.HttpStatusCode = int HttpStatusCode.OK then + let r = retrieveResult.Result :?> JobStatusEntity + let currentRow: RaftEvent.RaftJobEvent = RaftEvent.deserializeEvent r.JobStatus + // if current row job state is one of the next states down the line, then ignore current message altogether. + // Since current message is "late" + if currentRow.Message.State ??> decodedMessage.Message.State then + Some currentRow.Message + else + None + else + None + + match currentStatusWithHigherPrecedence with + | Some currentRowMessage -> + logInfo "Dropping new status message since current status has higher precedence : %A and new message state is : %A [current status: %A new message status: %s ]" + currentRowMessage.State decodedMessage.Message.State currentRowMessage message + | None -> + let entity = JobStatusEntity(decodedMessage.Message.JobId.ToString(), decodedMessage.Message.AgentName, message, ETag = retrieveResult.Etag) + let insertOp = TableOperation.InsertOrReplace(entity) + let! insertResult = table.ExecuteAsync(insertOp).ToAsync + if insertResult.HttpStatusCode <> int HttpStatusCode.NoContent then + //Table record got updated by someone else, figure out what to do next. + match decodedMessage.Message.State with + | JobState.Running -> + logInfo "Current message state is Running. The table-record was already updated. Dropping Current message: %s" message + // if we are updating running progress -> and record got updated by someone else. + // Then just discard current update. + () + | _ -> + // Any other + // Try to send message again. + logInfo "Current message failed to update the table record. Going to try again: %s" message + let message = ServiceBus.Message(RaftEvent.serializeToBytes decodedMessage) + do! communicationClients.JobEventsSender.SendAsync(message).ToAsync + else + let name, units = + if decodedMessage.Message.AgentName = decodedMessage.Message.JobId then + "Job", "job" + else + (sprintf "Task: %s" (if String.IsNullOrWhiteSpace decodedMessage.Message.Tool then "NotSet" else decodedMessage.Message.Tool)), "task" + + let collectToolMetrics() = + match decodedMessage.Message.Metrics with + | None -> () + | Some m -> + Central.Telemetry.TrackMetric( + TelemetryValues.BugsFound( + m.TotalBugBucketsCount, + name, + decodedMessage.Message.UtcEventTime), "Bugs") + + for (KeyValue(statusCode, count)) in m.ResponseCodeCounts do + Central.Telemetry.TrackMetric( + TelemetryValues.StatusCount( + statusCode, + count, + name, + decodedMessage.Message.UtcEventTime), "HttpRequests" + ) + + match decodedMessage.Message.State with + | JobState.Created -> + Central.Telemetry.TrackMetric(TelemetryValues.Created(name, decodedMessage.Message.UtcEventTime), units) + | JobState.Completed -> + Central.Telemetry.TrackMetric(TelemetryValues.Completed(name, decodedMessage.Message.UtcEventTime), units) + collectToolMetrics() + | JobState.Error -> + Central.Telemetry.TrackMetric(TelemetryValues.Error(name, decodedMessage.Message.UtcEventTime), units) + collectToolMetrics() + | JobState.TimedOut -> + Central.Telemetry.TrackMetric(TelemetryValues.TimedOut(name, decodedMessage.Message.UtcEventTime), units) + collectToolMetrics() + | JobState.ManuallyStopped -> + Central.Telemetry.TrackMetric(TelemetryValues.Deleted(name, decodedMessage.Message.UtcEventTime), units) + collectToolMetrics() + | JobState.Creating | JobState.Running -> () + + else + logError "Unhandled message type %s in message %s" eventType message + return () + } |> Async.StartAsTask + + let doDelete (azure: IAzure) (agentConfig: AgentConfig, _) (containerGroupName: string)= + async { + try + do! azure.ContainerGroups.DeleteByResourceGroupAsync(agentConfig.ResourceGroup, containerGroupName).ToAsync + return Result.Ok () + with ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + return Result.Error("Failed to delete Container Instance", ex.Message) + } + + // This function runs in response to a message in the webhook queue. + // It takes the message and posts it to the event grid. + // The message it receives is the "raw" message. The message does not have the webhook envelope wrapped around it. + let webhookMessage (logger:ILogger) (_, agentConfig: AgentConfig, communicationClients: CommunicationClients) (message: string) = + async { + let logInfo format = Printf.kprintf logger.LogInformation format + let logError format = Printf.kprintf logger.LogError format + logInfo "[WEBHOOK] message: %s" message + + let inline processMessage (jobId: string) (decodedMessage : RaftEvent.RaftJobEvent< ^T >) = + async { + let! table = getWebHookTable agentConfig.StorageTableConnectionString + let query = TableQuery().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, jobId.ToString())) + let! segment = table.ExecuteQuerySegmentedAsync(query, null) |> Async.AwaitTask + + if segment.Results.Count = 1 then + let webhookName = segment.Results.[0].RowKey + let envelope = + { + Topic = webhookName + Id = Guid.NewGuid().ToString() + EventType = decodedMessage.EventType.ToString() + Subject = decodedMessage.EventType.ToString() + EventTime = DateTime.UtcNow.ToString("O") + Data = decodedMessage.Message + DataVersion = "1.0" + } + + // Post the message to event grid. + let body = Microsoft.FSharpLu.Json.Compact.serialize [envelope] + logInfo "[WEBHOOK] body: %s" body + + use content = + let c = new System.Net.Http.StringContent(body) + c.Headers.Add("aeg-sas-key", agentConfig.EventGridKey) + c.Headers.ContentType <- Http.Headers.MediaTypeHeaderValue.Parse("application/json") + c + + let! response = communicationClients.WebhookSender.PostAsync(agentConfig.EventGridEndpoint, content) |> Async.AwaitTask + + if int response.StatusCode < 200 || int response.StatusCode > 299 then + logError "[WEBHOOK] Send failure: %O" response + else + logInfo "[WEBHOOK] Send response: %O" response + else + logInfo "No [WEBHOOK] set for job %O" jobId + } + + + let getMetadata jobId = + async { + let! jobTable = getJobTable agentConfig.StorageTableConnectionString + let getOperation = TableOperation.Retrieve(jobId, jobId) + let! retrieveResult = jobTable.ExecuteAsync(getOperation).ToAsync + + if retrieveResult.HttpStatusCode = int HttpStatusCode.OK then + let jobEntity = retrieveResult.Result :?> JobEntity + let webhookDefinition = Microsoft.FSharpLu.Json.Compact.deserialize(jobEntity.Webhook) + match webhookDefinition with + | Some webhook -> + logError "[WEBHOOK] webhook is not set in jobrequest for jobId: %A" jobId + return Some webhook.Metadata + | None -> return None + else + logError "[WEBHOOK] Getting job (to find pipeline data) failed with status code %d" retrieveResult.HttpStatusCode + return None + } + + let eventType = RaftEvent.getEventType message + if eventType = JobStatus.EventType then + let jobStatus : RaftEvent.RaftJobEvent = RaftEvent.deserializeEvent message + let! metadata = getMetadata jobStatus.Message.JobId + let updatedJobStatus = { jobStatus with + Message = { jobStatus.Message with + Metadata = metadata } + } + do! processMessage updatedJobStatus.Message.JobId updatedJobStatus + else if eventType = BugFound<_>.EventType then + let bugFound : RaftEvent.RaftJobEvent = RaftEvent.deserializeEvent message + let! metadata = getMetadata bugFound.Message.JobId + let updatedBugFound = { bugFound with + Message = { bugFound.Message with + Metadata = metadata } + } + + do! processMessage updatedBugFound.Message.JobId updatedBugFound + else + logError "[WEBHOOK] Unhandled webhook event type : %s in message :%s" eventType message + + return () + } |> Async.StartAsTask + + type Metric = + { + Average : float + TimeStamp: DateTime + } + + type MetricEvent = + { + ContainerGroupName: string + MetricName : string + MetricUnits: string + MetricData : Metric + } + + let metrics (logger: ILogger) (azure: IAzure) (containerGroup:IContainerGroup) (startTime: DateTime, endTime: DateTime) = + async { + let logInfo format = Printf.kprintf logger.LogInformation format + let logError format = Printf.kprintf logger.LogError format + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + let! metrics = + async { + try + let! metrics = azure.MetricDefinitions.ListByResourceAsync(containerGroup.Id).ToAsync + let! metricsList = + [ + for m in metrics -> + async { + let! res = m.DefineQuery().StartingFrom(startTime).EndsBefore(endTime).ExecuteAsync().ToAsync + return! [ + for r in res.Metrics -> + async { + let metricEvents: MetricEvent list = + [ + for t in r.Timeseries do + for d in t.Data do + if d.Average.HasValue then + yield + { + ContainerGroupName = containerGroup.Name + MetricName = r.Name.Value + MetricUnits = sprintf "%A" r.Unit + MetricData = + { + Average = d.Average.Value + TimeStamp = d.TimeStamp + } + } + ] + let metricsList = + metricEvents + |> List.map(fun event -> + match event.MetricName.ToLowerInvariant() with + | "networkbytestransmittedpersecond" -> + Some(TelemetryValues.AverageNetworkBytesTransmittedPerSecond(event.MetricData.Average, event.MetricData.TimeStamp), event.MetricUnits) + | "networkbytesreceivedpersecond" -> + Some(TelemetryValues.AverageNetworkBytesReceivedPerSecond(event.MetricData.Average, event.MetricData.TimeStamp), event.MetricUnits) + | "memoryusage" -> + Some(TelemetryValues.ContainerGroupAverageRAMUsageMB(event.MetricData.Average, event.MetricData.TimeStamp), event.MetricUnits) + | "cpuusage" -> + Some(TelemetryValues.ContainerGroupAverageCPUUsage(event.MetricData.Average, event.MetricData.TimeStamp), event.MetricUnits) + | _ -> + logError "[Metrics] Unexpected metric name - %s" event.MetricName + None + ) + |> List.filter Option.isSome + |> List.map (fun v -> v.Value) + + return metricsList + } + ] |> Async.Sequential + } + ] |> Async.Sequential + return Some metricsList + with + | ex -> + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + logError "[Metrics] Failed to get metric %s due to %A" containerGroup.Name ex + return None + } + stopWatch.Stop() + logInfo "[Metrics] Time took to run on-timer metrics collection for container group %s: %f seconds" containerGroup.Name stopWatch.Elapsed.TotalSeconds + return metrics + } + + let [] Terminated = "Terminated" + let [] Error = "Error" + let [] Succeeded = "Succeeded" + + /// Job is manually stopped if Container Group is Stopped explicitly (from portal, or by calling delete) + let isJobManuallyStopped (g: IContainerGroup) = + g.State = ContainerGroupStates.Stopped + + /// Job is finished if every container is terminated + let isJobRunFinished (g: IContainerGroup) = + if Tags.isGcReady g.Tags then + (g.State = ContainerGroupStates.Failed || g.ProvisioningState = ContainerGroupStates.Failed) + || + ( + (g.State = ContainerGroupStates.Succeeded || g.State = ContainerGroupStates.Stopped) + && + (g.Containers.Count = 0 || + (g.Containers.Count > 0 && + g.Containers + |> Seq.forall (fun (KeyValue(_, v)) -> + not <| isNull v.InstanceView && + v.InstanceView.CurrentState.State = Terminated + ) + ) + ) + ) + else + false + + // We want to allow all internal processes to complete before we + // force kill a container. + let durationSlack = TimeSpan.FromMinutes 60.0 + let isJobExpired (logger: ILogger) (g: IContainerGroup) = + let logInfo format = Printf.kprintf logger.LogInformation format + match Tags.getBoolFromTags g.Tags Tags.GCReady with + | Some true | None -> + if not <| g.Tags.ContainsKey Tags.Duration then + //if duration tag is not set, then let job run until it terminates + false + else + match Tags.getStartTime g.Tags, Tags.getDuration g.Tags with + | Some startTime, Some duration -> + let now = DateTime.UtcNow + let expirationTime = startTime + duration + durationSlack + if now > expirationTime then + logInfo "Running job expired: %s . %s: %A, %s: %A. UtcNow: %A, ExpirationTimeUtc: %A" g.Name Tags.StartTimeUtc startTime Tags.Duration duration now expirationTime + true + else + false + // If tags do not have correct values, then assume job expired + | None, None -> + logInfo "Running job assumed to be expired, since tags tracking start time and duration are not set: %s" g.Name + true + | Some _, None -> + logInfo "Running job assumed to be expired since %s tag is not set: %s" Tags.Duration g.Name + true + | None, Some _ -> + logInfo "Running job assumed to be expired since %s tag is not set: %s" Tags.StartTimeUtc g.Name + true + | Some false -> + logInfo "[GC] GC ready tag is set to false. Therefore job is not expired: %s" g.Name + false + + /// Get a sequence of containers that terminated due to error + let getContainersExitedWithError (g: IContainerGroup) = + g.Containers |> Seq.filter(fun (KeyValue(_, v)) -> + if not <| isNull v.InstanceView then + let currentState = v.InstanceView.CurrentState + currentState.DetailStatus = Error + else false) + |> Seq.map (fun (KeyValue(_, v)) -> v) + + + /// Calculate union of all container life times within container group + let calculateContainerGroupLifeSpan (g: IContainerGroup) = + (None, g.Containers) + ||> Seq.fold ( fun lifeSpan (KeyValue(_, v)) -> + if isNull v.InstanceView then + lifeSpan + else + let instance = v.InstanceView.CurrentState + match lifeSpan with + | None -> + let startTime = + if instance.StartTime.HasValue then instance.StartTime.Value else DateTime.UtcNow + let endTime = + if instance.FinishTime.HasValue then instance.FinishTime.Value else DateTime.UtcNow + Some (startTime, endTime) + | Some(s, e) -> + let startTime = + if instance.StartTime.HasValue then min instance.StartTime.Value s else s + let endTime = + if instance.FinishTime.HasValue then max instance.FinishTime.Value e else e + Some(startTime, endTime) + ) + + /// Garbage collect all finished jobs. + /// Job is finished if all containers are stopped or job is running longer than it's set duration. + /// - Collect and log container group metrics + /// + let gc (logger: ILogger) (azure: IAzure, agentConfig: AgentConfig, communicationClients: CommunicationClients) = + async { + + let logInfo format = Printf.kprintf logger.LogInformation format + let logError format = Printf.kprintf logger.LogError format + + let stopWatch = System.Diagnostics.Stopwatch() + stopWatch.Start() + + let rec processContainerGroups (containerGroups: Core.IPagedCollection) (numberOfSuccessfullDeletions: int, numberOfFailedDeletion: int) = + async { + if (isNull containerGroups) then + return (numberOfSuccessfullDeletions, numberOfFailedDeletion) + else + let successFullDeletionsCount, failedDeletionsCount = ref 0, ref 0 + for g in containerGroups do + try + let jobManuallyStopped = isJobManuallyStopped g + let jobRunFinished = isJobRunFinished g + + let! isExpired = + async { + if jobRunFinished || jobManuallyStopped then + // if job is GC ready, then it is already stopped. And therefore cannot be expired + return false + else if isJobExpired logger g then + //since job is expired, need to stop it and garbage collect it + logInfo "[GC] Stopping running job since it expired: %s" g.Name + do! stopJob g + return true + else + return false + } + + if jobRunFinished && not isExpired then + logInfo "[GC] All containers [Count: %d] terminated for container group: %s" g.Containers.Count g.Name + + if jobRunFinished || jobManuallyStopped || isExpired then + let instancesExitedWithError = getContainersExitedWithError g + + let state, details = + if isExpired then + JobState.TimedOut, [] + else if jobManuallyStopped then + JobState.ManuallyStopped, [] + else if Seq.isEmpty instancesExitedWithError then + JobState.Completed, [] + else + //There is at least one container that terminated with an error + JobState.Error, + ([], instancesExitedWithError |> List.ofSeq) + ||> List.fold (fun details v -> + let detail (name) (s: string) = + sprintf "[Agent:%s] %s: %s" v.Name name s + [ + detail "Exit Code" (sprintf "%A" v.InstanceView.CurrentState.ExitCode) + detail "State" (sprintf "%A" v.InstanceView.CurrentState.State) + detail "Detailed Status" (sprintf "%A" v.InstanceView.CurrentState.DetailStatus) + ] + @ details) + + let! metricsDetails = + async { + match calculateContainerGroupLifeSpan g with + | Some (startTime, endTime) -> + logInfo "[GC] Collecting metrics for %s from %A to %A" g.Name startTime endTime + match! metrics logger azure g (startTime - TimeSpan.FromMinutes(5.0), endTime + TimeSpan.FromMinutes(5.0)) with + | None -> return [] + | Some ms -> + ms + |> Array.iter(fun metricsEvents -> + metricsEvents + |> Array.iter(fun events -> + events |> List.iter(fun event -> Central.Telemetry.TrackMetric event) + ) + ) + + let cpu, bytesReceived, bytesSent = + (([], [], []), ms) + ||> Array.fold(fun (cpu, bytesReceived, bytesSent) metricsEvents -> + ((cpu, bytesReceived, bytesSent), metricsEvents) + ||> Array.fold(fun (cpu, bytesReceived, bytesSent) events -> + ((cpu, bytesReceived, bytesSent), events) + ||> List.fold(fun (cpu, bytesReceived, bytesSent) (event, _) -> + match event with + | ContainerGroupAverageCPUUsage(v, _) -> + (v::cpu, bytesReceived, bytesSent) + | AverageNetworkBytesTransmittedPerSecond(v, _) -> + (cpu, bytesReceived, v::bytesSent) + | AverageNetworkBytesReceivedPerSecond(v, _) -> + (cpu, v::bytesReceived, bytesSent) + | _ -> + (cpu, bytesReceived, bytesSent) + ) + ) + ) + return [ + sprintf "CPU Average %f" (if List.isEmpty cpu then 0.0 else List.average cpu) + sprintf "Network total bytes received: %d" (if List.isEmpty bytesReceived then 0 else int (List.sum bytesReceived)) + sprintf "Network total bytes sent: %d" (if List.isEmpty bytesSent then 0 else int (List.sum bytesSent)) + ] + | None -> + logInfo "[Metrics] ignoring metrics collection since could not calculate container lifespan for container group: %s" g.Name + return [] + } + + do! postStatus communicationClients.JobEventsSender g.Name state (Some (details@metricsDetails)) + + for v in instancesExitedWithError do + let! failedContainerLogs = g.GetLogContentAsync(v.Name).ToAsync + + logInfo "[%s][%s][State:%A][DetailStatus: %A][ExitCode: %A] failed logs: %s\nEvents: %A" + g.Name v.Name + v.InstanceView.CurrentState.State + v.InstanceView.CurrentState.DetailStatus + v.InstanceView.CurrentState.ExitCode + failedContainerLogs + (v.InstanceView.Events |> Seq.map (fun e -> e.Name, e.Message)) + + logInfo "[GC] Deleting container group: %s" g.Name + let! result = doDelete azure (agentConfig, communicationClients) g.Name + + match result with + | Result.Ok() -> + incr successFullDeletionsCount + | Result.Error errors -> + logError "[GC] for container group %s failed to delete: %A" g.Name errors + incr failedDeletionsCount + with + | ex -> + logError "[GC] for container group: %s due to %A" g.Name ex + Central.Telemetry.TrackError (TelemetryValues.Exception ex) + + let! nextGroup = containerGroups.GetNextPageAsync().ToAsync + return! processContainerGroups nextGroup (numberOfSuccessfullDeletions + !successFullDeletionsCount, numberOfFailedDeletion + !failedDeletionsCount) + } + let! containerGroups = azure.ContainerGroups.ListByResourceGroupAsync(agentConfig.ResourceGroup).ToAsync + + let! numberOfSuccessfullfDeletions, numberOfFailedDeletions = processContainerGroups containerGroups (0, 0) + stopWatch.Stop() + if numberOfSuccessfullfDeletions <> 0 || numberOfFailedDeletions <> 0 then + Central.Telemetry.TrackMetric(GCRun(stopWatch.Elapsed.TotalSeconds, numberOfSuccessfullfDeletions, numberOfFailedDeletions), "seconds") + logInfo "[GC] Time took to run GC: %f seconds. Container Groups deleted [Successfully: %d; Failed: %d]" stopWatch.Elapsed.TotalSeconds numberOfSuccessfullfDeletions numberOfFailedDeletions + return () + } |> Async.StartAsTask diff --git a/src/Orchestrator/OrchestratorLogic/OrchestratorLogic.fsproj b/src/Orchestrator/OrchestratorLogic/OrchestratorLogic.fsproj new file mode 100644 index 0000000..8fee1dd --- /dev/null +++ b/src/Orchestrator/OrchestratorLogic/OrchestratorLogic.fsproj @@ -0,0 +1,36 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/RAFT.sln b/src/RAFT.sln new file mode 100644 index 0000000..455ae4d --- /dev/null +++ b/src/RAFT.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29721.120 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "RaftResultAnalyzer", "Agent\RaftResultAnalyzer\RaftResultAnalyzer.fsproj", "{06D9C309-2ABC-48E2-AFAE-96D4D63E757E}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "APIService", "APIService\ApiService\APIService.fsproj", "{71B94358-CC31-4A91-99D4-0B8FCED3AD8D}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "RestlerAgent", "Agent\RESTlerAgent\RestlerAgent.fsproj", "{A0C08B1C-9741-4EF0-8822-15B74C2E2C69}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "AzureAuth", "Agent\AzureAuth\AzureAuth.fsproj", "{28C9E068-8EF7-4D57-AD79-AF64D3B5638A}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "APIServiceTests", "APIService\ApiService\APIServiceTests\APIServiceTests.fsproj", "{19F65C0B-7818-4F56-B428-4FF79F945B91}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TestInfraLogic", "Test\TestInfraLogic\TestInfraLogic.fsproj", "{50DC6F9C-30B8-4A2A-B539-EB71F5FC6D6F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestInfraFunc", "Test\TestInfraFunc\TestInfraFunc.csproj", "{9C51647C-BC07-49AD-9940-642EDECC7B0A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orchestrator", "Orchestrator\Orchestrator\Orchestrator.csproj", "{4F661698-112F-4BB4-BC34-E1E9C0A07963}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "OrchestratorLogic", "Orchestrator\OrchestratorLogic\OrchestratorLogic.fsproj", "{BFE2B877-4015-4519-92D8-F6A633770B15}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {06D9C309-2ABC-48E2-AFAE-96D4D63E757E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {06D9C309-2ABC-48E2-AFAE-96D4D63E757E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06D9C309-2ABC-48E2-AFAE-96D4D63E757E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {06D9C309-2ABC-48E2-AFAE-96D4D63E757E}.Release|Any CPU.Build.0 = Release|Any CPU + {71B94358-CC31-4A91-99D4-0B8FCED3AD8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71B94358-CC31-4A91-99D4-0B8FCED3AD8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71B94358-CC31-4A91-99D4-0B8FCED3AD8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71B94358-CC31-4A91-99D4-0B8FCED3AD8D}.Release|Any CPU.Build.0 = Release|Any CPU + {A0C08B1C-9741-4EF0-8822-15B74C2E2C69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0C08B1C-9741-4EF0-8822-15B74C2E2C69}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0C08B1C-9741-4EF0-8822-15B74C2E2C69}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0C08B1C-9741-4EF0-8822-15B74C2E2C69}.Release|Any CPU.Build.0 = Release|Any CPU + {28C9E068-8EF7-4D57-AD79-AF64D3B5638A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28C9E068-8EF7-4D57-AD79-AF64D3B5638A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28C9E068-8EF7-4D57-AD79-AF64D3B5638A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28C9E068-8EF7-4D57-AD79-AF64D3B5638A}.Release|Any CPU.Build.0 = Release|Any CPU + {19F65C0B-7818-4F56-B428-4FF79F945B91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19F65C0B-7818-4F56-B428-4FF79F945B91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19F65C0B-7818-4F56-B428-4FF79F945B91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19F65C0B-7818-4F56-B428-4FF79F945B91}.Release|Any CPU.Build.0 = Release|Any CPU + {50DC6F9C-30B8-4A2A-B539-EB71F5FC6D6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50DC6F9C-30B8-4A2A-B539-EB71F5FC6D6F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50DC6F9C-30B8-4A2A-B539-EB71F5FC6D6F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50DC6F9C-30B8-4A2A-B539-EB71F5FC6D6F}.Release|Any CPU.Build.0 = Release|Any CPU + {9C51647C-BC07-49AD-9940-642EDECC7B0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C51647C-BC07-49AD-9940-642EDECC7B0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C51647C-BC07-49AD-9940-642EDECC7B0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C51647C-BC07-49AD-9940-642EDECC7B0A}.Release|Any CPU.Build.0 = Release|Any CPU + {4F661698-112F-4BB4-BC34-E1E9C0A07963}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F661698-112F-4BB4-BC34-E1E9C0A07963}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F661698-112F-4BB4-BC34-E1E9C0A07963}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F661698-112F-4BB4-BC34-E1E9C0A07963}.Release|Any CPU.Build.0 = Release|Any CPU + {BFE2B877-4015-4519-92D8-F6A633770B15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFE2B877-4015-4519-92D8-F6A633770B15}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFE2B877-4015-4519-92D8-F6A633770B15}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFE2B877-4015-4519-92D8-F6A633770B15}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F19F65F1-F41E-425D-B1DC-D425E267B007} + EndGlobalSection +EndGlobal diff --git a/src/Test/Dockerfile b/src/Test/Dockerfile new file mode 100644 index 0000000..0951f0a --- /dev/null +++ b/src/Test/Dockerfile @@ -0,0 +1,10 @@ +# IMPORTANT NOTE: List of all function-docker images can be found here +# https://hub.docker.com/_/microsoft-azure-functions-dotnet +# See FULL TAG LISTING at the bottom of the page for list of available images and versions + +FROM mcr.microsoft.com/azure-functions/dotnet:3.0 + +ENV AzureWebJobsScriptRoot=/home/site/wwwroot \ + AzureFunctionsJobHost__Logging__Console__IsEnabled=true + +COPY . /home/site/wwwroot diff --git a/src/Test/TestInfraFunc/.gitignore b/src/Test/TestInfraFunc/.gitignore new file mode 100644 index 0000000..ff5b00c --- /dev/null +++ b/src/Test/TestInfraFunc/.gitignore @@ -0,0 +1,264 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# Azure Functions localsettings file +local.settings.json + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/src/Test/TestInfraFunc/TestInfra.cs b/src/Test/TestInfraFunc/TestInfra.cs new file mode 100644 index 0000000..133e240 --- /dev/null +++ b/src/Test/TestInfraFunc/TestInfra.cs @@ -0,0 +1,70 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.WebJobs; +using Microsoft.Azure.WebJobs.Extensions.Http; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; + +namespace TestInfraFunc +{ + public static class TestInfra + { + private static String GetSetting(String envVariableName) + { + return Environment.GetEnvironmentVariable(envVariableName, EnvironmentVariableTarget.Process); + } + + static private string StorageTableConnectionString = GetSetting("RAFT_STORAGE_TABLE_CONNECTION_STRING"); + + [FunctionName("webhooks-trigger-test")] + public static async Task WebhookTriggerTest([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "test")] HttpRequest request, ILogger log) + { + string jobId = request.Query["jobId"]; + + if (string.IsNullOrEmpty(jobId)) + { + if (request.Method.ToLowerInvariant() == "post") + { + var s = new System.IO.StreamReader(request.Body); + var text = await s.ReadToEndAsync(); + log.LogInformation($"Body: {text}"); + //https://docs.microsoft.com/en-us/azure/event-grid/webhook-event-delivery + + var r = await TestInfraLogic.WebhooksTest.validation(log, text); + if (r.Item1) + { + log.LogInformation($"Returning validation code {r.Item2}"); + return new OkObjectResult(r.Item2); + } + else + { + await TestInfraLogic.WebhooksTest.post(log, StorageTableConnectionString, text); + return new OkResult(); + } + } + else + { + log.LogWarning($"Unhandled request method {request.Method} when job id is not set"); + return new BadRequestResult(); + } + } + else + { + if (request.Method.ToLowerInvariant() == "get") + { + log.LogInformation($"Getting webhook messages for job ${jobId}"); + var results = await TestInfraLogic.WebhooksTest.get(log, StorageTableConnectionString, jobId); + return new OkObjectResult(results); + } + else + { + log.LogWarning($"Unhandled request method {request.Method} when job id is ${jobId}"); + return new BadRequestResult(); + } + } + } + } +} diff --git a/src/Test/TestInfraFunc/TestInfraFunc.csproj b/src/Test/TestInfraFunc/TestInfraFunc.csproj new file mode 100644 index 0000000..c1add84 --- /dev/null +++ b/src/Test/TestInfraFunc/TestInfraFunc.csproj @@ -0,0 +1,21 @@ + + + netcoreapp3.1 + v3 + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + \ No newline at end of file diff --git a/src/Test/TestInfraFunc/host.json b/src/Test/TestInfraFunc/host.json new file mode 100644 index 0000000..bb3b8da --- /dev/null +++ b/src/Test/TestInfraFunc/host.json @@ -0,0 +1,11 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingExcludedTypes": "Request", + "samplingSettings": { + "isEnabled": true + } + } + } +} \ No newline at end of file diff --git a/src/Test/TestInfraLogic/Dockerfile b/src/Test/TestInfraLogic/Dockerfile new file mode 100644 index 0000000..889b61e --- /dev/null +++ b/src/Test/TestInfraLogic/Dockerfile @@ -0,0 +1,12 @@ +# IMPORTANT NOTE: List of all function-docker images can be found here +# https://hub.docker.com/_/microsoft-azure-functions-base +# https://mcr.microsoft.com/v2/azure-functions/base/tags/list + +# To enable ssh & remote debugging on app service change the base image to the one below +# FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appservice +FROM mcr.microsoft.com/azure-functions/dotnet:3.0 + +ENV AzureWebJobsScriptRoot=/home/site/wwwroot \ + AzureFunctionsJobHost__Logging__Console__IsEnabled=true + +COPY . /home/site/wwwroot diff --git a/src/Test/TestInfraLogic/TestInfraLogic.fsproj b/src/Test/TestInfraLogic/TestInfraLogic.fsproj new file mode 100644 index 0000000..b514cd1 --- /dev/null +++ b/src/Test/TestInfraLogic/TestInfraLogic.fsproj @@ -0,0 +1,31 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Test/TestInfraLogic/WebhooksTest.fs b/src/Test/TestInfraLogic/WebhooksTest.fs new file mode 100644 index 0000000..f2fa393 --- /dev/null +++ b/src/Test/TestInfraLogic/WebhooksTest.fs @@ -0,0 +1,156 @@ +namespace TestInfraLogic +open Microsoft.Extensions.Logging +open Microsoft.Azure.Cosmos.Table +open System.Net + +module WebhooksTest = + open Newtonsoft.Json + + type ValidationData = + { + ValidationCode : string + } + + type Validation = + { + Data : ValidationData + } + + type ValidationResponse = + { + ValidationResponse : string + } + + (* +[ + { + "id": "2d1781af-3a4c-4d7c-bd0c-e34b19da4e66", + "topic": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "subject": "", + "data": { + "validationCode": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6", + "validationUrl": "https://rp-eastus2.eventgrid.azure.net:553/eventsubscriptions/estest/validate?id=512d38b6-c7b8-40c8-89fe-f46f9e9622b6&t=2018-04-26T20:30:54.4538837Z&apiVersion=2018-05-01-preview&token=1A1A1A1A" + }, + "eventType": "Microsoft.EventGrid.SubscriptionValidationEvent", + "eventTime": "2018-01-25T22:12:19.4556811Z", + "metadataVersion": "1", + "dataVersion": "1" + } +] + +must return: +{ +"validationResponse": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6" +} +*) + type TupleAsArraySettings = + static member formatting = Newtonsoft.Json.Formatting.Indented + static member settings = + JsonSerializerSettings( + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore, + Converters = [| Microsoft.FSharpLu.Json.CompactUnionJsonConverter(true, true) |] + ) + type private J = Microsoft.FSharpLu.Json.With + + let getWebHooksTestTable connectionString = + async { + let TableName = "WebhooksTriggerTest" + let storageAccount = CloudStorageAccount.Parse(connectionString) + let tableClient = storageAccount.CreateCloudTableClient() + let table = tableClient.GetTableReference(TableName) + return table + } + + let validation (logger: ILogger) (msg: string) = + async { + match J.tryDeserialize msg with + | Choice1Of2 (v: Validation list) when not(List.isEmpty v) -> + match (List.head v).Data.ValidationCode with + | null -> return false, Unchecked.defaultof<_> + | code -> + logger.LogInformation(sprintf "Got Webhooks Validation message: %s" msg) + return true, {ValidationResponse = code} + | Choice1Of2 _ + | Choice2Of2 _ -> + return false, Unchecked.defaultof<_> + + } |> Async.StartAsTask + + + + type WebhookData = + { + JobId : string + } + + type Webhook = + { + Subject : string + Id : string + Data : WebhookData + EventType: string + } + + type WebhoookTestRecordEntity(jobId, webhookId, message) = + inherit TableEntity(partitionKey=jobId, rowKey=webhookId) + new() = WebhoookTestRecordEntity(null, null, null) + member val WebhoookTestRecordEntity : string = message with get, set + + let post (logger: ILogger, storageTableConnectionString: string) (msg: string) = + async { + logger.LogInformation(sprintf "Got Webhooks Test POST message: %s" msg) + + match J.tryDeserialize msg with + | Choice1Of2(webhookEvents: Webhook list) -> + if List.length webhookEvents <> 1 then + logger.LogWarning (sprintf "Expected only one webhook event, but got %d in %s" (List.length webhookEvents) msg) + + for event in webhookEvents do + if event.EventType = "BugFound" || event.EventType = "JobStatus" then + let! table = getWebHooksTestTable(storageTableConnectionString) + + let entity = WebhoookTestRecordEntity(event.Data.JobId, event.Id, msg) + + let insertOp = TableOperation.InsertOrReplace(entity) + let! insertResult = table.ExecuteAsync(insertOp) |> Async.AwaitTask + + if insertResult.HttpStatusCode = int HttpStatusCode.OK || insertResult.HttpStatusCode = int HttpStatusCode.NoContent then + () + else + let errMsg = sprintf "Failed to insert : %s into webhooks test table with error code : %A" msg insertResult.HttpStatusCode + logger.LogError errMsg + else + logger.LogInformation (sprintf "Ignoring webhook test event, since it is of unsupported event type : %s" event.EventType) + return () + | Choice2Of2 err -> + logger.LogWarning (sprintf "Failed to deserialize %s due to %s" msg err) + return () + + } |> Async.StartAsTask + + let get (logger: ILogger, storageTableConnectionString: string) (jobId: string) = + async { + logger.LogInformation(sprintf "Got Webhooks Test GET for job id : %A" jobId) + let! table = getWebHooksTestTable(storageTableConnectionString) + let query = TableQuery().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, jobId.ToString())) + + let rec getResults(results: ResizeArray<_>) = + async { + let! segment = table.ExecuteQuerySegmentedAsync(query, null) |> Async.AwaitTask + if segment = null then + return results + else + results.AddRange(segment.Results) + if segment.ContinuationToken = null then + return results + else + return! getResults results + } + let! results = getResults (ResizeArray()) + let results = results |> Seq.map (fun r -> r.WebhoookTestRecordEntity) + + logger.LogInformation (sprintf "Retrieved Webhook Test Results for jobId %s : %A" jobId results) + return results + } |> Async.StartAsTask + diff --git a/src/global.json b/src/global.json new file mode 100644 index 0000000..a545d08 --- /dev/null +++ b/src/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "2.1" + } +} diff --git a/src/restler/Dockerfile b/src/restler/Dockerfile new file mode 100644 index 0000000..017546b --- /dev/null +++ b/src/restler/Dockerfile @@ -0,0 +1,17 @@ +FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine + +COPY ./compiler /RESTler/compiler +COPY ./restler /RESTler/restler + +#Get the source code for the engine, and +#copy source code to the image +#RESTler Python dependency +RUN apk add --no-cache python3 +RUN python3 -m ensurepip +RUN pip3 install --upgrade pip +RUN pip3 install requests +RUN pip3 install requests +RUN pip3 install applicationinsights +COPY ./src/engine /RESTler/engine +RUN python3 -m compileall -b /RESTler/engine +COPY ./resultsAnalyzer /RESTler/resultsAnalyzer