├── .editorconfig ├── .gitattributes ├── .github ├── CODEOWNERS ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── SECURITY.md ├── dependabot.yml └── workflows │ ├── build.yml │ └── update-dotnet-sdk.yml ├── .gitignore ├── .vscode └── extensions.json ├── AspNet.Security.OpenId.Providers.ruleset ├── AspNet.Security.OpenId.Providers.sln ├── CODE_OF_CONDUCT.md ├── Directory.Build.props ├── Directory.Build.targets ├── Directory.Packages.props ├── LICENSE ├── NuGet.config ├── README.md ├── build.cmd ├── build.ps1 ├── build.sh ├── eng ├── Signing.props ├── Version.Details.xml ├── Versions.props ├── common │ ├── BuildConfiguration │ │ └── build-configuration.json │ ├── CIBuild.cmd │ ├── PSScriptAnalyzerSettings.psd1 │ ├── README.md │ ├── SetupNugetSources.ps1 │ ├── SetupNugetSources.sh │ ├── build.cmd │ ├── build.ps1 │ ├── build.sh │ ├── cibuild.sh │ ├── cross │ │ ├── arm │ │ │ └── tizen │ │ │ │ └── tizen.patch │ │ ├── arm64 │ │ │ └── tizen │ │ │ │ └── tizen.patch │ │ ├── armel │ │ │ ├── armel.jessie.patch │ │ │ └── tizen │ │ │ │ └── tizen.patch │ │ ├── build-android-rootfs.sh │ │ ├── build-rootfs.sh │ │ ├── riscv64 │ │ │ └── tizen │ │ │ │ └── tizen.patch │ │ ├── tizen-build-rootfs.sh │ │ ├── tizen-fetch.sh │ │ ├── toolchain.cmake │ │ └── x86 │ │ │ └── tizen │ │ │ └── tizen.patch │ ├── darc-init.ps1 │ ├── darc-init.sh │ ├── dotnet-install.cmd │ ├── dotnet-install.ps1 │ ├── dotnet-install.sh │ ├── enable-cross-org-publishing.ps1 │ ├── generate-locproject.ps1 │ ├── generate-sbom-prep.ps1 │ ├── generate-sbom-prep.sh │ ├── helixpublish.proj │ ├── init-tools-native.cmd │ ├── init-tools-native.ps1 │ ├── init-tools-native.sh │ ├── internal-feed-operations.ps1 │ ├── internal-feed-operations.sh │ ├── internal │ │ ├── Directory.Build.props │ │ ├── NuGet.config │ │ └── Tools.csproj │ ├── loc │ │ └── P22DotNetHtmlLocalization.lss │ ├── msbuild.ps1 │ ├── msbuild.sh │ ├── native │ │ ├── CommonLibrary.psm1 │ │ ├── common-library.sh │ │ ├── init-compiler.sh │ │ ├── init-distro-rid.sh │ │ ├── init-os-and-arch.sh │ │ ├── install-cmake-test.sh │ │ ├── install-cmake.sh │ │ └── install-tool.ps1 │ ├── pipeline-logging-functions.ps1 │ ├── pipeline-logging-functions.sh │ ├── post-build │ │ ├── check-channel-consistency.ps1 │ │ ├── nuget-validation.ps1 │ │ ├── nuget-verification.ps1 │ │ ├── publish-using-darc.ps1 │ │ ├── redact-logs.ps1 │ │ ├── sourcelink-validation.ps1 │ │ └── symbols-validation.ps1 │ ├── retain-build.ps1 │ ├── sdk-task.ps1 │ ├── sdl │ │ ├── NuGet.config │ │ ├── configure-sdl-tool.ps1 │ │ ├── execute-all-sdl-tools.ps1 │ │ ├── extract-artifact-archives.ps1 │ │ ├── extract-artifact-packages.ps1 │ │ ├── init-sdl.ps1 │ │ ├── packages.config │ │ ├── run-sdl.ps1 │ │ ├── sdl.ps1 │ │ └── trim-assets-version.ps1 │ ├── tools.ps1 │ └── tools.sh └── key.snk ├── global.json ├── package-icon.png ├── samples └── Mvc.Client │ ├── Controllers │ ├── AuthenticationController.cs │ └── HomeController.cs │ ├── Extensions │ └── HttpContextExtensions.cs │ ├── Mvc.Client.csproj │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Startup.cs │ └── Views │ ├── Authentication │ └── SignIn.cshtml │ ├── Home │ └── Index.cshtml │ ├── Shared │ └── _Layout.cshtml │ └── _ViewStart.cshtml ├── src ├── AspNet.Security.OpenId.Steam │ ├── AspNet.Security.OpenId.Steam.csproj │ ├── SteamAuthenticationConstants.cs │ ├── SteamAuthenticationDefaults.cs │ ├── SteamAuthenticationExtensions.cs │ ├── SteamAuthenticationHandler.cs │ └── SteamAuthenticationOptions.cs └── AspNet.Security.OpenId │ ├── AspNet.Security.OpenId.csproj │ ├── Events │ ├── OpenIdAuthenticatedContext.cs │ └── OpenIdRedirectContext.cs │ ├── OpenIdAuthenticationConfiguration.cs │ ├── OpenIdAuthenticationConstants.cs │ ├── OpenIdAuthenticationDefaults.cs │ ├── OpenIdAuthenticationEvents.cs │ ├── OpenIdAuthenticationExtensions.cs │ ├── OpenIdAuthenticationHandler.cs │ ├── OpenIdAuthenticationInitializer.cs │ ├── OpenIdAuthenticationMessage.cs │ └── OpenIdAuthenticationOptions.cs └── test └── AspNet.Security.OpenId.Providers.Tests ├── AspNet.Security.OpenId.Providers.Tests.csproj ├── Infrastructure ├── ApplicationFactory.cs ├── HttpRequestInterceptionFilter.cs ├── LoopbackRedirectHandler.cs └── Program.cs ├── OpenIdTests`1.cs ├── Steam ├── SteamTests.cs └── bundle.json └── xunit.runner.json /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet-contrib/AspNet.Security.OpenId.Providers/14f7589c93e6a3c5210e9d414651390808eb36eb/.github/CODEOWNERS -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Feature requests and bugs 4 | 5 | Please submit any feature requests or bugs as an [issue](https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers) in GitHub. 6 | 7 | ## New OpenID Providers 8 | 9 | New OpenID providers are added by the community, not the maintainers. 10 | 11 | If you wish to add a new provider that is not already part of this repository, fork the repository and try and implement it yourself. 12 | 13 | Then you can submit it back as a Pull Request for inclusion here. 14 | 15 | ## Pull requests 16 | 17 | If you wish to contribute code, please consider the guidelines below: 18 | 19 | 1. Create an issue detailing the motivation for the change. 20 | 1. Fork the repository to your GitHub account. 21 | 1. Create a branch to work on your changes. 22 | 1. Please follow the existing code style and [EditorConfig](http://editorconfig.org/) formatting settings. 23 | 1. If fixing a bug or adding new functionality, add or update any tests you deem appropriate. 24 | 1. Ensure ```build.cmd```/```build.sh``` runs with no errors or warnings and all the tests pass. 25 | 1. Open a pull request against the ```dev``` branch, referencing your issue, if appropriate. 26 | 27 | Once your pull request is opened, the project maintainers will review it as soon as they are able. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Provider name 2 | 3 | _State which provider(s) you are experiencing an issue with._ 4 | 5 | ### Expected behavior 6 | 7 | _Explain what you expected to happen._ 8 | 9 | ### Actual behavior 10 | 11 | _Explain what actually happened. If an exception occurred, please include a stack trace if available._ 12 | 13 | ### Steps to reproduce 14 | 15 | _A concise and repeatable example of how to illustrate the issue._ 16 | 17 | ### Additional information 18 | 19 | _Any additional information that may be useful, such as the version of the package you are using or the version of .NET Core._ 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a bug report to help us improve AspNet.Security.OpenId.Providers 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | _A clear and concise description of what the bug is. State which provider(s) the bug relates to._ 9 | 10 | **Steps To reproduce** 11 | _A concise and repeatable example of how to illustrate the issue._ 12 | 13 | **Expected behaviour** 14 | _A clear and concise description of what you expected to happen._ 15 | 16 | **Actual behaviour** 17 | _A clear and concise description of what actually happened. If an exception occurred, please include a stack trace if available._ 18 | 19 | **System information:** 20 | - OS: [e.g. Windows 10] 21 | - Library Version [e.g. 2.0.1] 22 | - .NET version (e.g. output from `dotnet --info`) 23 | 24 | **Additional context** 25 | _Add any other context about the problem here._ 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for a new feature for AspNet.Security.OpenID.Providers 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. For example: _I'm always frustrated when [...]_ 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | _Summarize the changes this Pull Request makes._ 2 | 3 | _If adding a new provider, please ensure you have included appropriate test(s)._ 4 | 5 | _Please include a reference to a GitHub issue if appropriate._ 6 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security policy 2 | 3 | ## Supported Versions 4 | 5 | Only versions of the providers that target versions of ASP.NET Core that are in support by Microsoft are supported by the maintainers. 6 | 7 | The .NET Core and ASP.NET Core support policy, including currently supported versions, can be found at the [.NET and .NET Core Support Policy page](https://dotnet.microsoft.com/platform/support/policy/dotnet-core). 8 | 9 | ## Reporting a Vulnerability 10 | 11 | Security issues and bugs should be reported privately by emailing [contact@kevinchalet.com](mailto:contact@kevinchalet.com). 12 | 13 | You should receive a response within 48 hours. If for some reason you do not, please follow up via email to ensure we received your original message. 14 | 15 | Please do not open GitHub issues for anything you think might have a security implication. 16 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | groups: 6 | actions: 7 | patterns: 8 | - actions/* 9 | schedule: 10 | interval: daily 11 | time: "06:30" 12 | timezone: Europe/London 13 | - package-ecosystem: nuget 14 | directory: "/" 15 | schedule: 16 | interval: daily 17 | time: "06:30" 18 | timezone: Europe/London 19 | open-pull-requests-limit: 99 20 | ignore: 21 | - dependency-name: "AngleSharp" 22 | - dependency-name: "Microsoft.AspNetCore.Mvc.Testing" 23 | update-types: ["version-update:semver-major"] 24 | - dependency-name: "Microsoft.AspNetCore.TestHost" 25 | update-types: ["version-update:semver-major"] 26 | - dependency-name: "Microsoft.IdentityModel.Protocols" 27 | - dependency-name: "Microsoft.DotNet.Arcade.Sdk" 28 | - dependency-name: "Microsoft.DotNet.Helix.Sdk" 29 | -------------------------------------------------------------------------------- /.github/workflows/update-dotnet-sdk.yml: -------------------------------------------------------------------------------- 1 | name: update-dotnet-sdk 2 | 3 | on: 4 | schedule: 5 | - cron: '00 19 * * TUE' 6 | workflow_dispatch: 7 | inputs: 8 | branch: 9 | description: 'The branch to run the SDK updates for.' 10 | required: false 11 | type: choice 12 | options: 13 | - 'dev' 14 | - 'dev-v9' 15 | default: 'dev' 16 | 17 | permissions: 18 | contents: read 19 | pull-requests: read 20 | 21 | jobs: 22 | update-sdk: 23 | name: Update .NET SDK 24 | uses: martincostello/update-dotnet-sdk/.github/workflows/update-dotnet-sdk.yml@ee0555fe74ccf33a1d2f0a18e0acc0b190914d33 # v3.8.2 25 | permissions: 26 | contents: write 27 | pull-requests: write 28 | with: 29 | labels: 'dependencies,.NET' 30 | ref: ${{ inputs.branch || 'dev' }} 31 | update-nuget-packages: true 32 | user-email: ${{ vars.SERVICE_ACCOUNT_GIT_EMAIL }} 33 | user-name: ${{ vars.SERVICE_ACCOUNT_GIT_NAME }} 34 | secrets: 35 | application-id: ${{ secrets.SERVICE_ACCOUNT_ID }} 36 | application-private-key: ${{ secrets.SERVICE_ACCOUNT_PRIVATE_KEY }} 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # VS 14 temporary folder 5 | *.sln.ide/ 6 | target/ 7 | .nuget/ 8 | .vs/ 9 | .build/ 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.sln.docstates 15 | project.lock.json 16 | 17 | # Build results 18 | 19 | .dotnet 20 | artifacts/ 21 | coverage.* 22 | [Dd]ebug/ 23 | [Rr]elease/ 24 | x64/ 25 | [Bb]in/ 26 | [Oo]bj/ 27 | 28 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 29 | !packages/*/build/ 30 | 31 | # MSTest test Results 32 | [Tt]est[Rr]esult*/ 33 | [Bb]uild[Ll]og.* 34 | *.coverage 35 | 36 | *_i.c 37 | *_p.c 38 | *.ilk 39 | *.binlog 40 | *.meta 41 | *.obj 42 | *.pch 43 | *.pdb 44 | *.pgc 45 | *.pgd 46 | *.rsp 47 | *.sbr 48 | *.tlb 49 | *.tli 50 | *.tlh 51 | *.tmp 52 | *.tmp_proj 53 | *.log 54 | *.vspscc 55 | *.vssscc 56 | .builds 57 | *.pidb 58 | *.log 59 | *.scc 60 | 61 | # Visual C++ cache files 62 | ipch/ 63 | *.aps 64 | *.ncb 65 | *.opensdf 66 | *.sdf 67 | *.cachefile 68 | 69 | # Visual Studio profiler 70 | *.psess 71 | *.vsp 72 | *.vspx 73 | 74 | # Guidance Automation Toolkit 75 | *.gpState 76 | 77 | # ReSharper is a .NET coding add-in 78 | _ReSharper*/ 79 | *.[Rr]e[Ss]harper 80 | 81 | # TeamCity is a build add-in 82 | _TeamCity* 83 | 84 | # DotCover is a Code Coverage Tool 85 | *.dotCover 86 | 87 | # NCrunch 88 | *.ncrunch* 89 | .*crunch*.local.xml 90 | 91 | # Installshield output folder 92 | [Ee]xpress/ 93 | 94 | # DocProject is a documentation generator add-in 95 | DocProject/buildhelp/ 96 | DocProject/Help/*.HxT 97 | DocProject/Help/*.HxC 98 | DocProject/Help/*.hhc 99 | DocProject/Help/*.hhk 100 | DocProject/Help/*.hhp 101 | DocProject/Help/Html2 102 | DocProject/Help/html 103 | 104 | # Click-Once directory 105 | publish/ 106 | 107 | # Publish Web Output 108 | *.pubxml 109 | *.Publish.xml 110 | 111 | # NuGet Packages Directory 112 | .packages/ 113 | packages/ 114 | 115 | # Windows Azure Build Output 116 | csx 117 | *.build.csdef 118 | 119 | # Windows Store app package directory 120 | AppPackages/ 121 | 122 | # Others 123 | sql/ 124 | *.Cache 125 | ClientBin/ 126 | [Ss]tyle[Cc]op.* 127 | ~$* 128 | *~ 129 | *.dbmdl 130 | *.[Pp]ublish.xml 131 | *.publishsettings 132 | 133 | # RIA/Silverlight projects 134 | Generated_Code/ 135 | 136 | # Backup & report files from converting an old project file to a newer 137 | # Visual Studio version. Backup files are not needed, because we have git ;-) 138 | _UpgradeReport_Files/ 139 | Backup*/ 140 | UpgradeLog*.XML 141 | UpgradeLog*.htm 142 | 143 | # SQL Server files 144 | *.mdf 145 | *.ldf 146 | 147 | 148 | #LightSwitch generated files 149 | GeneratedArtifacts/ 150 | _Pvt_Extensions/ 151 | ModelManifest.xml 152 | 153 | # ========================= 154 | # Windows detritus 155 | # ========================= 156 | 157 | # Windows image file caches 158 | Thumbs.db 159 | ehthumbs.db 160 | 161 | # Folder config file 162 | Desktop.ini 163 | 164 | # Recycle Bin used on file shares 165 | $RECYCLE.BIN/ 166 | 167 | # Mac desktop service store files 168 | .DS_Store 169 | 170 | # Domain verification files 171 | .well-known/ 172 | 173 | # Public and Private keys 174 | *.cer 175 | *.csr 176 | *.key 177 | *.p7b 178 | *.p8 179 | *.p12 180 | *.pem 181 | *.pfx 182 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "editorconfig.editorconfig", 4 | "github.vscode-github-actions", 5 | "ms-dotnettools.csharp" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /AspNet.Security.OpenId.Providers.ruleset: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team [through a GitHub issue](https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers/issues). All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net9.0 7 | latest 8 | $(NoWarn);CA1515;CS1591 9 | true 10 | true 11 | portable 12 | true 13 | snupkg 14 | $(DefineConstants);JETBRAINS_ANNOTATIONS 15 | enable 16 | true 17 | true 18 | 19 | 20 | 21 | aspnet-contrib 22 | $(MSBuildThisFileDirectory)\eng\key.snk 23 | true 24 | false 25 | false 26 | 00240000048000001402000006020000002400005253413100100000010001003509225ad4352617a51a898866d28f3164f3a89953b492dd8b582c76a6fa8679429392db97c54d73cd0a1ddff3f5d91aeb2e861405060d2ac56240cbac91bbe3dfe529db7f32c2c4526b70339f842802fd454d99e1197e201be8c1cda0e2d94359d2a08fed162330f13ef437f0f73a4c5109bfff23db52a936fbdb1b680de3ff6a20d75bd40f326afd7c2b2f20400063b58ed59cf6f105397ee6889fd87bdf33519c30407cd5ee79bdfb93573941e165205282e2c65cae25e564fd431c872f470a24049be5ea617912d7c0b3a2296479d57976e8cc45516009218b183c48f66912fd682d7160f5c2a3a867259243fc2d42a63607ecabcc05a5239851090cee5f8b213da8a3c02ad87f4ceffe2d0793df8420492c7d6919eb2c7fc1657dc966d474d0423cc4b78707832e5c8957bdcb5a0350b10be17f15e95e58b66694c18c5b7a18e7728ed5d27c6993490f280bbbf5e6a93da32ad93fc5bffdadb19a10ac2fe8a41034ff26d2302d9df2b2785907bb65cc86fb0d52ec9876ca0101d15be19937ef7ecf8b5c68d9f0ebafb865effefc3029d89bc5205f537051615e3a0a26ac103c383429c8a718486c82b907b72430ee96b55a6d9dcbb293a65db643a441513d95f6382439a2aedbe86285398e47f83271b93b9bfc00c8ed5be88a710ccd078ea53ca917d96f859ef8e4792e8b6cf0c45db27520fbb5a3cfa4c621e4f983da 27 | fa9e7b608b196fab 28 | 29 | 30 | 34 | 35 | 36 | true 37 | $(_AspNetContribBuildNumber) 38 | 39 | 40 | 41 | aspnet-contrib 42 | $(Authors) 43 | <_ProjectCopyright>© AspNet.Security.OAuth.Providers contributors. All rights reserved. 44 | $(MSBuildThisFileDirectory)package-icon.png 45 | https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 46 | Apache-2.0 47 | README.md 48 | git 49 | git://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 50 | 51 | 52 | 53 | AllEnabledByDefault 54 | $(MSBuildThisFileDirectory)AspNet.Security.OpenId.Providers.ruleset 55 | true 56 | 57 | 58 | 59 | true 60 | true 61 | true 62 | true 63 | true 64 | 65 | 66 | 67 | $(IsPackable) 68 | 69 | 70 | 71 | $([MSBuild]::MakeRelative($(RepoRoot), $(MSBuildProjectDirectory))) 72 | false 73 | 74 | 75 | 76 | true 77 | true 78 | true 79 | true 80 | false 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | enable 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | $(Authors) 14 | $(_ProjectCopyright) 15 | false 16 | false 17 | 18 | 19 | 24 | 25 | 26 | $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)')) 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AspNet.Security.OpenId.Providers 2 | 3 | **AspNet.Security.OpenId.Providers** is a **collection of security middleware** that you can use in your **ASP.NET Core** application to support OpenID 2.0 authentication providers like **[Steam](https://steampowered.com/)** or **[Wargaming](https://wargaming.net/)**. It is directly inspired by **[Jerrie Pelser](https://github.com/jerriep)**'s initiative, **[Owin.Security.Providers](https://github.com/RockstarLabs/OwinOAuthProviders)**. 4 | 5 | **The latest official release can be found on [NuGet](https://www.nuget.org/profiles/aspnet-contrib) and the nightly builds on [MyGet](https://www.myget.org/gallery/aspnet-contrib)**. 6 | 7 | [![Build status](https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers/actions/workflows/build.yml/badge.svg?branch=dev&event=push)](https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers/actions/workflows/build.yml?query=event%3Apush+branch%3Adev) 8 | 9 | ## Getting started 10 | 11 | **Adding external authentication to your application is a breeze** and just requires a few lines in your `Startup` class: 12 | 13 | ```csharp 14 | public void ConfigureServices(IServiceCollection services) 15 | { 16 | services.AddAuthentication(options => { /* Authentication options */ }) 17 | .AddSteam() 18 | .AddOpenId("StackExchange", "StackExchange", options => 19 | { 20 | options.Authority = new Uri("https://openid.stackexchange.com/"); 21 | options.CallbackPath = "/signin-stackexchange"; 22 | }); 23 | } 24 | 25 | public void Configure(IApplicationBuilder app) 26 | { 27 | app.UseAuthentication(); 28 | } 29 | ``` 30 | 31 | See the [/samples](https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers/tree/dev/samples) directory for a complete sample **using ASP.NET Core MVC and supporting multiple external providers**. 32 | 33 | ## Contributing 34 | 35 | **AspNet.Security.OpenId.Providers** is actively maintained by: 36 | 37 | - **[Kévin Chalet](https://github.com/kevinchalet)** ([@kevin_chalet](https://twitter.com/kevin_chalet)). 38 | - **[Martin Costello](https://github.com/martincostello)** ([@martin_costello](https://twitter.com/martin_costello)). 39 | 40 | We would love it if you could help contributing to this repository. 41 | 42 | ## Security policy 43 | 44 | Please see [SECURITY.md](./.github/SECURITY.md) for information about reporting security issues and bugs. 45 | 46 | ## Support 47 | 48 | **Need help or wanna share your thoughts?** Don't hesitate to join us on Gitter or ask your question on StackOverflow: 49 | 50 | - **Gitter: [https://gitter.im/aspnet-contrib/AspNet.Security.OpenId.Providers](https://gitter.im/aspnet-contrib/AspNet.Security.OpenId.Providers)** 51 | - **StackOverflow: [https://stackoverflow.com/questions/tagged/aspnet-contrib](https://stackoverflow.com/questions/tagged/aspnet-contrib)** 52 | 53 | ## License 54 | 55 | This project is licensed under the **Apache License**. This means that you can use, modify and distribute it freely. See [https://www.apache.org/licenses/LICENSE-2.0.html](https://www.apache.org/licenses/LICENSE-2.0.html) for more details. 56 | 57 | ## Providers 58 | 59 | Links to the latest stable and nightly NuGet packages for each provider, as well as a link to their integration documentation are listed in the table below. 60 | 61 | If a provider you're looking for does not exist, consider making a PR to add one. 62 | 63 | | Provider | Stable | Nightly | Documentation | 64 | |:-:|:-:|:-:|:-:| 65 | | OpenId | [![NuGet](https://img.shields.io/nuget/v/AspNet.Security.OpenId?logo=nuget&label=NuGet&color=blue)](https://www.nuget.org/packages/AspNet.Security.OpenId/ "Download AspNet.Security.OpenId from NuGet.org") | [![MyGet](https://img.shields.io/myget/aspnet-contrib/vpre/AspNet.Security.OpenId?logo=nuget&label=MyGet&color=blue)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OpenId "Download AspNet.Security.OpenId from MyGet.org") | N/A | 66 | | Steam | [![NuGet](https://img.shields.io/nuget/v/AspNet.Security.OpenId.Steam?logo=nuget&label=NuGet&color=blue)](https://www.nuget.org/packages/AspNet.Security.OpenId.Steam/ "Download AspNet.Security.OpenId.Steam from NuGet.org") | [![MyGet](https://img.shields.io/myget/aspnet-contrib/vpre/AspNet.Security.OpenId.Steam?logo=nuget&label=MyGet&color=blue)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OpenId.Steam "Download AspNet.Security.OpenId.Steam from MyGet.org") | [Documentation](https://steamcommunity.com/dev "Steam developer documentation") | 67 | 68 | 71 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0eng\common\Build.ps1""" -restore -build %*" 3 | exit /b %ErrorLevel% 4 | -------------------------------------------------------------------------------- /build.ps1: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = "Stop" 2 | 3 | Set-Location $PSScriptRoot 4 | $buildFile = Join-Path "$PSScriptRoot" "Run.ps1" 5 | 6 | &"$buildFile" @args 7 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | 5 | # resolve $SOURCE until the file is no longer a symlink 6 | while [[ -h $source ]]; do 7 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 8 | source="$(readlink "$source")" 9 | 10 | # if $source was a relative symlink, we need to resolve it relative to the path where the 11 | # symlink file was located 12 | [[ $source != /* ]] && source="$scriptroot/$source" 13 | done 14 | 15 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 16 | "$scriptroot/eng/common/build.sh" --build --restore $@ 17 | -------------------------------------------------------------------------------- /eng/Signing.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /eng/Version.Details.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | https://github.com/dotnet/arcade 10 | dd332f2d4e21daa8b79f84251ab156af9a0b11b2 11 | 12 | 13 | 14 | 15 | https://github.com/dotnet/arcade 16 | dd332f2d4e21daa8b79f84251ab156af9a0b11b2 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /eng/Versions.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 5 | 0 6 | 0 7 | $(MajorVersion).$(MinorVersion).$(PatchVersion) 8 | 9.0.0 9 | preview 10 | 11 | Preview $(PreReleaseVersionIteration) 12 | false 13 | release 14 | true 15 | false 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /eng/common/BuildConfiguration/build-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "RetryCountLimit": 1, 3 | "RetryByAnyError": false 4 | } 5 | -------------------------------------------------------------------------------- /eng/common/CIBuild.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0Build.ps1""" -restore -build -test -sign -pack -publish -ci %*" -------------------------------------------------------------------------------- /eng/common/PSScriptAnalyzerSettings.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | IncludeRules=@('PSAvoidUsingCmdletAliases', 3 | 'PSAvoidUsingWMICmdlet', 4 | 'PSAvoidUsingPositionalParameters', 5 | 'PSAvoidUsingInvokeExpression', 6 | 'PSUseDeclaredVarsMoreThanAssignments', 7 | 'PSUseCmdletCorrectly', 8 | 'PSStandardDSCFunctionsInResource', 9 | 'PSUseIdenticalMandatoryParametersForDSC', 10 | 'PSUseIdenticalParametersForDSC') 11 | } -------------------------------------------------------------------------------- /eng/common/README.md: -------------------------------------------------------------------------------- 1 | # Don't touch this folder 2 | 3 | uuuuuuuuuuuuuuuuuuuu 4 | u" uuuuuuuuuuuuuuuuuu "u 5 | u" u$$$$$$$$$$$$$$$$$$$$u "u 6 | u" u$$$$$$$$$$$$$$$$$$$$$$$$u "u 7 | u" u$$$$$$$$$$$$$$$$$$$$$$$$$$$$u "u 8 | u" u$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$u "u 9 | u" u$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$u "u 10 | $ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $ 11 | $ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $ 12 | $ $$$" ... "$... ...$" ... "$$$ ... "$$$ $ 13 | $ $$$u `"$$$$$$$ $$$ $$$$$ $$ $$$ $$$ $ 14 | $ $$$$$$uu "$$$$ $$$ $$$$$ $$ """ u$$$ $ 15 | $ $$$""$$$ $$$$ $$$u "$$$" u$$ $$$$$$$$ $ 16 | $ $$$$....,$$$$$..$$$$$....,$$$$..$$$$$$$$ $ 17 | $ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $ 18 | "u "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" u" 19 | "u "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" u" 20 | "u "$$$$$$$$$$$$$$$$$$$$$$$$$$$$" u" 21 | "u "$$$$$$$$$$$$$$$$$$$$$$$$" u" 22 | "u "$$$$$$$$$$$$$$$$$$$$" u" 23 | "u """""""""""""""""" u" 24 | """""""""""""""""""" 25 | 26 | !!! Changes made in this directory are subject to being overwritten by automation !!! 27 | 28 | The files in this directory are shared by all Arcade repos and managed by automation. If you need to make changes to these files, open an issue or submit a pull request to https://github.com/dotnet/arcade first. 29 | -------------------------------------------------------------------------------- /eng/common/build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0build.ps1""" %*" 3 | exit /b %ErrorLevel% 4 | -------------------------------------------------------------------------------- /eng/common/cibuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | 5 | # resolve $SOURCE until the file is no longer a symlink 6 | while [[ -h $source ]]; do 7 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 8 | source="$(readlink "$source")" 9 | 10 | # if $source was a relative symlink, we need to resolve it relative to the path where 11 | # the symlink file was located 12 | [[ $source != /* ]] && source="$scriptroot/$source" 13 | done 14 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 15 | 16 | . "$scriptroot/build.sh" --restore --build --test --pack --publish --ci $@ -------------------------------------------------------------------------------- /eng/common/cross/arm/tizen/tizen.patch: -------------------------------------------------------------------------------- 1 | diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so 2 | --- a/usr/lib/libc.so 2016-12-30 23:00:08.284951863 +0900 3 | +++ b/usr/lib/libc.so 2016-12-30 23:00:32.140951815 +0900 4 | @@ -2,4 +2,4 @@ 5 | Use the shared library, but some functions are only in 6 | the static library, so try that secondarily. */ 7 | OUTPUT_FORMAT(elf32-littlearm) 8 | -GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux-armhf.so.3 ) ) 9 | +GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux-armhf.so.3 ) ) 10 | -------------------------------------------------------------------------------- /eng/common/cross/arm64/tizen/tizen.patch: -------------------------------------------------------------------------------- 1 | diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so 2 | --- a/usr/lib64/libc.so 2016-12-30 23:00:08.284951863 +0900 3 | +++ b/usr/lib64/libc.so 2016-12-30 23:00:32.140951815 +0900 4 | @@ -2,4 +2,4 @@ 5 | Use the shared library, but some functions are only in 6 | the static library, so try that secondarily. */ 7 | OUTPUT_FORMAT(elf64-littleaarch64) 8 | -GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /lib/ld-linux-aarch64.so.1 ) ) 9 | +GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux-aarch64.so.1 ) ) 10 | -------------------------------------------------------------------------------- /eng/common/cross/armel/armel.jessie.patch: -------------------------------------------------------------------------------- 1 | diff -u -r a/usr/include/urcu/uatomic/generic.h b/usr/include/urcu/uatomic/generic.h 2 | --- a/usr/include/urcu/uatomic/generic.h 2014-10-22 15:00:58.000000000 -0700 3 | +++ b/usr/include/urcu/uatomic/generic.h 2020-10-30 21:38:28.550000000 -0700 4 | @@ -69,10 +69,10 @@ 5 | #endif 6 | #ifdef UATOMIC_HAS_ATOMIC_SHORT 7 | case 2: 8 | - return __sync_val_compare_and_swap_2(addr, old, _new); 9 | + return __sync_val_compare_and_swap_2((uint16_t*) addr, old, _new); 10 | #endif 11 | case 4: 12 | - return __sync_val_compare_and_swap_4(addr, old, _new); 13 | + return __sync_val_compare_and_swap_4((uint32_t*) addr, old, _new); 14 | #if (CAA_BITS_PER_LONG == 64) 15 | case 8: 16 | return __sync_val_compare_and_swap_8(addr, old, _new); 17 | @@ -109,7 +109,7 @@ 18 | return; 19 | #endif 20 | case 4: 21 | - __sync_and_and_fetch_4(addr, val); 22 | + __sync_and_and_fetch_4((uint32_t*) addr, val); 23 | return; 24 | #if (CAA_BITS_PER_LONG == 64) 25 | case 8: 26 | @@ -148,7 +148,7 @@ 27 | return; 28 | #endif 29 | case 4: 30 | - __sync_or_and_fetch_4(addr, val); 31 | + __sync_or_and_fetch_4((uint32_t*) addr, val); 32 | return; 33 | #if (CAA_BITS_PER_LONG == 64) 34 | case 8: 35 | @@ -187,7 +187,7 @@ 36 | return __sync_add_and_fetch_2(addr, val); 37 | #endif 38 | case 4: 39 | - return __sync_add_and_fetch_4(addr, val); 40 | + return __sync_add_and_fetch_4((uint32_t*) addr, val); 41 | #if (CAA_BITS_PER_LONG == 64) 42 | case 8: 43 | return __sync_add_and_fetch_8(addr, val); 44 | -------------------------------------------------------------------------------- /eng/common/cross/armel/tizen/tizen.patch: -------------------------------------------------------------------------------- 1 | diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so 2 | --- a/usr/lib/libc.so 2016-12-30 23:00:08.284951863 +0900 3 | +++ b/usr/lib/libc.so 2016-12-30 23:00:32.140951815 +0900 4 | @@ -2,4 +2,4 @@ 5 | Use the shared library, but some functions are only in 6 | the static library, so try that secondarily. */ 7 | OUTPUT_FORMAT(elf32-littlearm) 8 | -GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.3 ) ) 9 | +GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux.so.3 ) ) 10 | -------------------------------------------------------------------------------- /eng/common/cross/build-android-rootfs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | __NDK_Version=r21 4 | 5 | usage() 6 | { 7 | echo "Creates a toolchain and sysroot used for cross-compiling for Android." 8 | echo 9 | echo "Usage: $0 [BuildArch] [ApiLevel]" 10 | echo 11 | echo "BuildArch is the target architecture of Android. Currently only arm64 is supported." 12 | echo "ApiLevel is the target Android API level. API levels usually match to Android releases. See https://source.android.com/source/build-numbers.html" 13 | echo 14 | echo "By default, the toolchain and sysroot will be generated in cross/android-rootfs/toolchain/[BuildArch]. You can change this behavior" 15 | echo "by setting the TOOLCHAIN_DIR environment variable" 16 | echo 17 | echo "By default, the NDK will be downloaded into the cross/android-rootfs/android-ndk-$__NDK_Version directory. If you already have an NDK installation," 18 | echo "you can set the NDK_DIR environment variable to have this script use that installation of the NDK." 19 | echo "By default, this script will generate a file, android_platform, in the root of the ROOTFS_DIR directory that contains the RID for the supported and tested Android build: android.28-arm64. This file is to replace '/etc/os-release', which is not available for Android." 20 | exit 1 21 | } 22 | 23 | __ApiLevel=28 # The minimum platform for arm64 is API level 21 but the minimum version that support glob(3) is 28. See $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/glob.h 24 | __BuildArch=arm64 25 | __AndroidArch=aarch64 26 | __AndroidToolchain=aarch64-linux-android 27 | 28 | for i in "$@" 29 | do 30 | lowerI="$(echo $i | tr "[:upper:]" "[:lower:]")" 31 | case $lowerI in 32 | -?|-h|--help) 33 | usage 34 | exit 1 35 | ;; 36 | arm64) 37 | __BuildArch=arm64 38 | __AndroidArch=aarch64 39 | __AndroidToolchain=aarch64-linux-android 40 | ;; 41 | arm) 42 | __BuildArch=arm 43 | __AndroidArch=arm 44 | __AndroidToolchain=arm-linux-androideabi 45 | ;; 46 | *[0-9]) 47 | __ApiLevel=$i 48 | ;; 49 | *) 50 | __UnprocessedBuildArgs="$__UnprocessedBuildArgs $i" 51 | ;; 52 | esac 53 | done 54 | 55 | # Obtain the location of the bash script to figure out where the root of the repo is. 56 | __ScriptBaseDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 57 | 58 | __CrossDir="$__ScriptBaseDir/../../../.tools/android-rootfs" 59 | 60 | if [[ ! -f "$__CrossDir" ]]; then 61 | mkdir -p "$__CrossDir" 62 | fi 63 | 64 | # Resolve absolute path to avoid `../` in build logs 65 | __CrossDir="$( cd "$__CrossDir" && pwd )" 66 | 67 | __NDK_Dir="$__CrossDir/android-ndk-$__NDK_Version" 68 | __lldb_Dir="$__CrossDir/lldb" 69 | __ToolchainDir="$__CrossDir/android-ndk-$__NDK_Version" 70 | 71 | if [[ -n "$TOOLCHAIN_DIR" ]]; then 72 | __ToolchainDir=$TOOLCHAIN_DIR 73 | fi 74 | 75 | if [[ -n "$NDK_DIR" ]]; then 76 | __NDK_Dir=$NDK_DIR 77 | fi 78 | 79 | echo "Target API level: $__ApiLevel" 80 | echo "Target architecture: $__BuildArch" 81 | echo "NDK location: $__NDK_Dir" 82 | echo "Target Toolchain location: $__ToolchainDir" 83 | 84 | # Download the NDK if required 85 | if [ ! -d $__NDK_Dir ]; then 86 | echo Downloading the NDK into $__NDK_Dir 87 | mkdir -p $__NDK_Dir 88 | wget -q --progress=bar:force:noscroll --show-progress https://dl.google.com/android/repository/android-ndk-$__NDK_Version-linux-x86_64.zip -O $__CrossDir/android-ndk-$__NDK_Version-linux-x86_64.zip 89 | unzip -q $__CrossDir/android-ndk-$__NDK_Version-linux-x86_64.zip -d $__CrossDir 90 | fi 91 | 92 | if [ ! -d $__lldb_Dir ]; then 93 | mkdir -p $__lldb_Dir 94 | echo Downloading LLDB into $__lldb_Dir 95 | wget -q --progress=bar:force:noscroll --show-progress https://dl.google.com/android/repository/lldb-2.3.3614996-linux-x86_64.zip -O $__CrossDir/lldb-2.3.3614996-linux-x86_64.zip 96 | unzip -q $__CrossDir/lldb-2.3.3614996-linux-x86_64.zip -d $__lldb_Dir 97 | fi 98 | 99 | echo "Download dependencies..." 100 | __TmpDir=$__CrossDir/tmp/$__BuildArch/ 101 | mkdir -p "$__TmpDir" 102 | 103 | # combined dependencies for coreclr, installer and libraries 104 | __AndroidPackages="libicu" 105 | __AndroidPackages+=" libandroid-glob" 106 | __AndroidPackages+=" liblzma" 107 | __AndroidPackages+=" krb5" 108 | __AndroidPackages+=" openssl" 109 | 110 | for path in $(wget -qO- https://packages.termux.dev/termux-main-21/dists/stable/main/binary-$__AndroidArch/Packages |\ 111 | grep -A15 "Package: \(${__AndroidPackages// /\\|}\)" | grep -v "static\|tool" | grep Filename); do 112 | 113 | if [[ "$path" != "Filename:" ]]; then 114 | echo "Working on: $path" 115 | wget -qO- https://packages.termux.dev/termux-main-21/$path | dpkg -x - "$__TmpDir" 116 | fi 117 | done 118 | 119 | cp -R "$__TmpDir/data/data/com.termux/files/usr/"* "$__ToolchainDir/sysroot/usr/" 120 | 121 | # Generate platform file for build.sh script to assign to __DistroRid 122 | echo "Generating platform file..." 123 | echo "RID=android.${__ApiLevel}-${__BuildArch}" > $__ToolchainDir/sysroot/android_platform 124 | 125 | echo "Now to build coreclr, libraries and installers; run:" 126 | echo ROOTFS_DIR=\$\(realpath $__ToolchainDir/sysroot\) ./build.sh --cross --arch $__BuildArch \ 127 | --subsetCategory coreclr 128 | echo ROOTFS_DIR=\$\(realpath $__ToolchainDir/sysroot\) ./build.sh --cross --arch $__BuildArch \ 129 | --subsetCategory libraries 130 | echo ROOTFS_DIR=\$\(realpath $__ToolchainDir/sysroot\) ./build.sh --cross --arch $__BuildArch \ 131 | --subsetCategory installer 132 | -------------------------------------------------------------------------------- /eng/common/cross/riscv64/tizen/tizen.patch: -------------------------------------------------------------------------------- 1 | diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so 2 | --- a/usr/lib64/libc.so 2016-12-30 23:00:08.284951863 +0900 3 | +++ b/usr/lib64/libc.so 2016-12-30 23:00:32.140951815 +0900 4 | @@ -2,4 +2,4 @@ 5 | Use the shared library, but some functions are only in 6 | the static library, so try that secondarily. */ 7 | OUTPUT_FORMAT(elf64-littleriscv) 8 | -GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-riscv64-lp64d.so.1 ) ) 9 | +GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux-riscv64-lp64d.so.1 ) ) 10 | -------------------------------------------------------------------------------- /eng/common/cross/tizen-build-rootfs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | ARCH=$1 5 | LINK_ARCH=$ARCH 6 | 7 | case "$ARCH" in 8 | arm) 9 | TIZEN_ARCH="armv7hl" 10 | ;; 11 | armel) 12 | TIZEN_ARCH="armv7l" 13 | LINK_ARCH="arm" 14 | ;; 15 | arm64) 16 | TIZEN_ARCH="aarch64" 17 | ;; 18 | x86) 19 | TIZEN_ARCH="i686" 20 | ;; 21 | x64) 22 | TIZEN_ARCH="x86_64" 23 | LINK_ARCH="x86" 24 | ;; 25 | riscv64) 26 | TIZEN_ARCH="riscv64" 27 | LINK_ARCH="riscv" 28 | ;; 29 | *) 30 | echo "Unsupported architecture for tizen: $ARCH" 31 | exit 1 32 | esac 33 | 34 | __CrossDir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 35 | __TIZEN_CROSSDIR="$__CrossDir/${ARCH}/tizen" 36 | 37 | if [[ -z "$ROOTFS_DIR" ]]; then 38 | echo "ROOTFS_DIR is not defined." 39 | exit 1; 40 | fi 41 | 42 | TIZEN_TMP_DIR=$ROOTFS_DIR/tizen_tmp 43 | mkdir -p $TIZEN_TMP_DIR 44 | 45 | # Download files 46 | echo ">>Start downloading files" 47 | VERBOSE=1 $__CrossDir/tizen-fetch.sh $TIZEN_TMP_DIR $TIZEN_ARCH 48 | echo "<>Start constructing Tizen rootfs" 51 | TIZEN_RPM_FILES=`ls $TIZEN_TMP_DIR/*.rpm` 52 | cd $ROOTFS_DIR 53 | for f in $TIZEN_RPM_FILES; do 54 | rpm2cpio $f | cpio -idm --quiet 55 | done 56 | echo "<>Start configuring Tizen rootfs" 63 | ln -sfn asm-${LINK_ARCH} ./usr/include/asm 64 | patch -p1 < $__TIZEN_CROSSDIR/tizen.patch 65 | if [[ "$TIZEN_ARCH" == "riscv64" ]]; then 66 | echo "Fixing broken symlinks in $PWD" 67 | rm ./usr/lib64/libresolv.so 68 | ln -s ../../lib64/libresolv.so.2 ./usr/lib64/libresolv.so 69 | rm ./usr/lib64/libpthread.so 70 | ln -s ../../lib64/libpthread.so.0 ./usr/lib64/libpthread.so 71 | rm ./usr/lib64/libdl.so 72 | ln -s ../../lib64/libdl.so.2 ./usr/lib64/libdl.so 73 | rm ./usr/lib64/libutil.so 74 | ln -s ../../lib64/libutil.so.1 ./usr/lib64/libutil.so 75 | rm ./usr/lib64/libm.so 76 | ln -s ../../lib64/libm.so.6 ./usr/lib64/libm.so 77 | rm ./usr/lib64/librt.so 78 | ln -s ../../lib64/librt.so.1 ./usr/lib64/librt.so 79 | rm ./lib/ld-linux-riscv64-lp64d.so.1 80 | ln -s ../lib64/ld-linux-riscv64-lp64d.so.1 ./lib/ld-linux-riscv64-lp64d.so.1 81 | fi 82 | echo "</dev/null; then 5 | VERBOSE=0 6 | fi 7 | 8 | Log() 9 | { 10 | if [ $VERBOSE -ge 1 ]; then 11 | echo ${@:2} 12 | fi 13 | } 14 | 15 | Inform() 16 | { 17 | Log 1 -e "\x1B[0;34m$@\x1B[m" 18 | } 19 | 20 | Debug() 21 | { 22 | Log 2 -e "\x1B[0;32m$@\x1B[m" 23 | } 24 | 25 | Error() 26 | { 27 | >&2 Log 0 -e "\x1B[0;31m$@\x1B[m" 28 | } 29 | 30 | Fetch() 31 | { 32 | URL=$1 33 | FILE=$2 34 | PROGRESS=$3 35 | if [ $VERBOSE -ge 1 ] && [ $PROGRESS ]; then 36 | CURL_OPT="--progress-bar" 37 | else 38 | CURL_OPT="--silent" 39 | fi 40 | curl $CURL_OPT $URL > $FILE 41 | } 42 | 43 | hash curl 2> /dev/null || { Error "Require 'curl' Aborting."; exit 1; } 44 | hash xmllint 2> /dev/null || { Error "Require 'xmllint' Aborting."; exit 1; } 45 | hash sha256sum 2> /dev/null || { Error "Require 'sha256sum' Aborting."; exit 1; } 46 | 47 | TMPDIR=$1 48 | if [ ! -d $TMPDIR ]; then 49 | TMPDIR=./tizen_tmp 50 | Debug "Create temporary directory : $TMPDIR" 51 | mkdir -p $TMPDIR 52 | fi 53 | 54 | TIZEN_ARCH=$2 55 | 56 | TIZEN_URL=http://download.tizen.org/snapshots/TIZEN/Tizen 57 | BUILD_XML=build.xml 58 | REPOMD_XML=repomd.xml 59 | PRIMARY_XML=primary.xml 60 | TARGET_URL="http://__not_initialized" 61 | 62 | Xpath_get() 63 | { 64 | XPATH_RESULT='' 65 | XPATH=$1 66 | XML_FILE=$2 67 | RESULT=$(xmllint --xpath $XPATH $XML_FILE) 68 | if [[ -z ${RESULT// } ]]; then 69 | Error "Can not find target from $XML_FILE" 70 | Debug "Xpath = $XPATH" 71 | exit 1 72 | fi 73 | XPATH_RESULT=$RESULT 74 | } 75 | 76 | fetch_tizen_pkgs_init() 77 | { 78 | TARGET=$1 79 | PROFILE=$2 80 | Debug "Initialize TARGET=$TARGET, PROFILE=$PROFILE" 81 | 82 | TMP_PKG_DIR=$TMPDIR/tizen_${PROFILE}_pkgs 83 | if [ -d $TMP_PKG_DIR ]; then rm -rf $TMP_PKG_DIR; fi 84 | mkdir -p $TMP_PKG_DIR 85 | 86 | PKG_URL=$TIZEN_URL/$PROFILE/latest 87 | 88 | BUILD_XML_URL=$PKG_URL/$BUILD_XML 89 | TMP_BUILD=$TMP_PKG_DIR/$BUILD_XML 90 | TMP_REPOMD=$TMP_PKG_DIR/$REPOMD_XML 91 | TMP_PRIMARY=$TMP_PKG_DIR/$PRIMARY_XML 92 | TMP_PRIMARYGZ=${TMP_PRIMARY}.gz 93 | 94 | Fetch $BUILD_XML_URL $TMP_BUILD 95 | 96 | Debug "fetch $BUILD_XML_URL to $TMP_BUILD" 97 | 98 | TARGET_XPATH="//build/buildtargets/buildtarget[@name=\"$TARGET\"]/repo[@type=\"binary\"]/text()" 99 | Xpath_get $TARGET_XPATH $TMP_BUILD 100 | TARGET_PATH=$XPATH_RESULT 101 | TARGET_URL=$PKG_URL/$TARGET_PATH 102 | 103 | REPOMD_URL=$TARGET_URL/repodata/repomd.xml 104 | PRIMARY_XPATH='string(//*[local-name()="data"][@type="primary"]/*[local-name()="location"]/@href)' 105 | 106 | Fetch $REPOMD_URL $TMP_REPOMD 107 | 108 | Debug "fetch $REPOMD_URL to $TMP_REPOMD" 109 | 110 | Xpath_get $PRIMARY_XPATH $TMP_REPOMD 111 | PRIMARY_XML_PATH=$XPATH_RESULT 112 | PRIMARY_URL=$TARGET_URL/$PRIMARY_XML_PATH 113 | 114 | Fetch $PRIMARY_URL $TMP_PRIMARYGZ 115 | 116 | Debug "fetch $PRIMARY_URL to $TMP_PRIMARYGZ" 117 | 118 | gunzip $TMP_PRIMARYGZ 119 | 120 | Debug "unzip $TMP_PRIMARYGZ to $TMP_PRIMARY" 121 | } 122 | 123 | fetch_tizen_pkgs() 124 | { 125 | ARCH=$1 126 | PACKAGE_XPATH_TPL='string(//*[local-name()="metadata"]/*[local-name()="package"][*[local-name()="name"][text()="_PKG_"]][*[local-name()="arch"][text()="_ARCH_"]]/*[local-name()="location"]/@href)' 127 | 128 | PACKAGE_CHECKSUM_XPATH_TPL='string(//*[local-name()="metadata"]/*[local-name()="package"][*[local-name()="name"][text()="_PKG_"]][*[local-name()="arch"][text()="_ARCH_"]]/*[local-name()="checksum"]/text())' 129 | 130 | for pkg in ${@:2} 131 | do 132 | Inform "Fetching... $pkg" 133 | XPATH=${PACKAGE_XPATH_TPL/_PKG_/$pkg} 134 | XPATH=${XPATH/_ARCH_/$ARCH} 135 | Xpath_get $XPATH $TMP_PRIMARY 136 | PKG_PATH=$XPATH_RESULT 137 | 138 | XPATH=${PACKAGE_CHECKSUM_XPATH_TPL/_PKG_/$pkg} 139 | XPATH=${XPATH/_ARCH_/$ARCH} 140 | Xpath_get $XPATH $TMP_PRIMARY 141 | CHECKSUM=$XPATH_RESULT 142 | 143 | PKG_URL=$TARGET_URL/$PKG_PATH 144 | PKG_FILE=$(basename $PKG_PATH) 145 | PKG_PATH=$TMPDIR/$PKG_FILE 146 | 147 | Debug "Download $PKG_URL to $PKG_PATH" 148 | Fetch $PKG_URL $PKG_PATH true 149 | 150 | echo "$CHECKSUM $PKG_PATH" | sha256sum -c - > /dev/null 151 | if [ $? -ne 0 ]; then 152 | Error "Fail to fetch $PKG_URL to $PKG_PATH" 153 | Debug "Checksum = $CHECKSUM" 154 | exit 1 155 | fi 156 | done 157 | } 158 | 159 | if [ "$TIZEN_ARCH" == "riscv64" ]; then 160 | BASE="Tizen-Base-RISCV" 161 | UNIFIED="Tizen-Unified-RISCV" 162 | else 163 | BASE="Tizen-Base" 164 | UNIFIED="Tizen-Unified" 165 | fi 166 | 167 | Inform "Initialize ${TIZEN_ARCH} base" 168 | fetch_tizen_pkgs_init standard $BASE 169 | Inform "fetch common packages" 170 | fetch_tizen_pkgs ${TIZEN_ARCH} gcc gcc-devel-static glibc glibc-devel libicu libicu-devel libatomic linux-glibc-devel keyutils keyutils-devel libkeyutils 171 | Inform "fetch coreclr packages" 172 | fetch_tizen_pkgs ${TIZEN_ARCH} libgcc libstdc++ libstdc++-devel libunwind libunwind-devel lttng-ust-devel lttng-ust userspace-rcu-devel userspace-rcu 173 | if [ "$TIZEN_ARCH" != "riscv64" ]; then 174 | fetch_tizen_pkgs ${TIZEN_ARCH} lldb lldb-devel 175 | fi 176 | Inform "fetch corefx packages" 177 | fetch_tizen_pkgs ${TIZEN_ARCH} libcom_err libcom_err-devel zlib zlib-devel libopenssl11 libopenssl1.1-devel krb5 krb5-devel 178 | 179 | Inform "Initialize standard unified" 180 | fetch_tizen_pkgs_init standard $UNIFIED 181 | Inform "fetch corefx packages" 182 | fetch_tizen_pkgs ${TIZEN_ARCH} gssdp gssdp-devel tizen-release 183 | 184 | -------------------------------------------------------------------------------- /eng/common/cross/x86/tizen/tizen.patch: -------------------------------------------------------------------------------- 1 | diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so 2 | --- a/usr/lib/libc.so 2016-12-30 23:00:08.284951863 +0900 3 | +++ b/usr/lib/libc.so 2016-12-30 23:00:32.140951815 +0900 4 | @@ -2,4 +2,4 @@ 5 | Use the shared library, but some functions are only in 6 | the static library, so try that secondarily. */ 7 | OUTPUT_FORMAT(elf32-i386) 8 | -GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) ) 9 | +GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux.so.2 ) ) 10 | -------------------------------------------------------------------------------- /eng/common/darc-init.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | $darcVersion = $null, 3 | $versionEndpoint = 'https://maestro.dot.net/api/assets/darc-version?api-version=2020-02-20', 4 | $verbosity = 'minimal', 5 | $toolpath = $null 6 | ) 7 | 8 | . $PSScriptRoot\tools.ps1 9 | 10 | function InstallDarcCli ($darcVersion, $toolpath) { 11 | $darcCliPackageName = 'microsoft.dotnet.darc' 12 | 13 | $dotnetRoot = InitializeDotNetCli -install:$true 14 | $dotnet = "$dotnetRoot\dotnet.exe" 15 | $toolList = & "$dotnet" tool list -g 16 | 17 | if ($toolList -like "*$darcCliPackageName*") { 18 | & "$dotnet" tool uninstall $darcCliPackageName -g 19 | } 20 | 21 | # If the user didn't explicitly specify the darc version, 22 | # query the Maestro API for the correct version of darc to install. 23 | if (-not $darcVersion) { 24 | $darcVersion = $(Invoke-WebRequest -Uri $versionEndpoint -UseBasicParsing).Content 25 | } 26 | 27 | $arcadeServicesSource = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' 28 | 29 | Write-Host "Installing Darc CLI version $darcVersion..." 30 | Write-Host 'You may need to restart your command window if this is the first dotnet tool you have installed.' 31 | if (-not $toolpath) { 32 | Write-Host "'$dotnet' tool install $darcCliPackageName --version $darcVersion --add-source '$arcadeServicesSource' -v $verbosity -g" 33 | & "$dotnet" tool install $darcCliPackageName --version $darcVersion --add-source "$arcadeServicesSource" -v $verbosity -g 34 | }else { 35 | Write-Host "'$dotnet' tool install $darcCliPackageName --version $darcVersion --add-source '$arcadeServicesSource' -v $verbosity --tool-path '$toolpath'" 36 | & "$dotnet" tool install $darcCliPackageName --version $darcVersion --add-source "$arcadeServicesSource" -v $verbosity --tool-path "$toolpath" 37 | } 38 | } 39 | 40 | try { 41 | InstallDarcCli $darcVersion $toolpath 42 | } 43 | catch { 44 | Write-Host $_.ScriptStackTrace 45 | Write-PipelineTelemetryError -Category 'Darc' -Message $_ 46 | ExitWithExitCode 1 47 | } -------------------------------------------------------------------------------- /eng/common/darc-init.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | darcVersion='' 5 | versionEndpoint='https://maestro.dot.net/api/assets/darc-version?api-version=2020-02-20' 6 | verbosity='minimal' 7 | 8 | while [[ $# > 0 ]]; do 9 | opt="$(echo "$1" | tr "[:upper:]" "[:lower:]")" 10 | case "$opt" in 11 | --darcversion) 12 | darcVersion=$2 13 | shift 14 | ;; 15 | --versionendpoint) 16 | versionEndpoint=$2 17 | shift 18 | ;; 19 | --verbosity) 20 | verbosity=$2 21 | shift 22 | ;; 23 | --toolpath) 24 | toolpath=$2 25 | shift 26 | ;; 27 | *) 28 | echo "Invalid argument: $1" 29 | usage 30 | exit 1 31 | ;; 32 | esac 33 | 34 | shift 35 | done 36 | 37 | # resolve $source until the file is no longer a symlink 38 | while [[ -h "$source" ]]; do 39 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 40 | source="$(readlink "$source")" 41 | # if $source was a relative symlink, we need to resolve it relative to the path where the 42 | # symlink file was located 43 | [[ $source != /* ]] && source="$scriptroot/$source" 44 | done 45 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 46 | 47 | . "$scriptroot/tools.sh" 48 | 49 | if [ -z "$darcVersion" ]; then 50 | darcVersion=$(curl -X GET "$versionEndpoint" -H "accept: text/plain") 51 | fi 52 | 53 | function InstallDarcCli { 54 | local darc_cli_package_name="microsoft.dotnet.darc" 55 | 56 | InitializeDotNetCli true 57 | local dotnet_root=$_InitializeDotNetCli 58 | 59 | if [ -z "$toolpath" ]; then 60 | local tool_list=$($dotnet_root/dotnet tool list -g) 61 | if [[ $tool_list = *$darc_cli_package_name* ]]; then 62 | echo $($dotnet_root/dotnet tool uninstall $darc_cli_package_name -g) 63 | fi 64 | else 65 | local tool_list=$($dotnet_root/dotnet tool list --tool-path "$toolpath") 66 | if [[ $tool_list = *$darc_cli_package_name* ]]; then 67 | echo $($dotnet_root/dotnet tool uninstall $darc_cli_package_name --tool-path "$toolpath") 68 | fi 69 | fi 70 | 71 | local arcadeServicesSource="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" 72 | 73 | echo "Installing Darc CLI version $darcVersion..." 74 | echo "You may need to restart your command shell if this is the first dotnet tool you have installed." 75 | if [ -z "$toolpath" ]; then 76 | echo $($dotnet_root/dotnet tool install $darc_cli_package_name --version $darcVersion --add-source "$arcadeServicesSource" -v $verbosity -g) 77 | else 78 | echo $($dotnet_root/dotnet tool install $darc_cli_package_name --version $darcVersion --add-source "$arcadeServicesSource" -v $verbosity --tool-path "$toolpath") 79 | fi 80 | } 81 | 82 | InstallDarcCli 83 | -------------------------------------------------------------------------------- /eng/common/dotnet-install.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0dotnet-install.ps1""" %*" -------------------------------------------------------------------------------- /eng/common/dotnet-install.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding(PositionalBinding=$false)] 2 | Param( 3 | [string] $verbosity = 'minimal', 4 | [string] $architecture = '', 5 | [string] $version = 'Latest', 6 | [string] $runtime = 'dotnet', 7 | [string] $RuntimeSourceFeed = '', 8 | [string] $RuntimeSourceFeedKey = '' 9 | ) 10 | 11 | . $PSScriptRoot\tools.ps1 12 | 13 | $dotnetRoot = Join-Path $RepoRoot '.dotnet' 14 | 15 | $installdir = $dotnetRoot 16 | try { 17 | if ($architecture -and $architecture.Trim() -eq 'x86') { 18 | $installdir = Join-Path $installdir 'x86' 19 | } 20 | InstallDotNet $installdir $version $architecture $runtime $true -RuntimeSourceFeed $RuntimeSourceFeed -RuntimeSourceFeedKey $RuntimeSourceFeedKey 21 | } 22 | catch { 23 | Write-Host $_.ScriptStackTrace 24 | Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_ 25 | ExitWithExitCode 1 26 | } 27 | 28 | ExitWithExitCode 0 29 | -------------------------------------------------------------------------------- /eng/common/dotnet-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | # resolve $source until the file is no longer a symlink 5 | while [[ -h "$source" ]]; do 6 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 7 | source="$(readlink "$source")" 8 | # if $source was a relative symlink, we need to resolve it relative to the path where the 9 | # symlink file was located 10 | [[ $source != /* ]] && source="$scriptroot/$source" 11 | done 12 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 13 | 14 | . "$scriptroot/tools.sh" 15 | 16 | version='Latest' 17 | architecture='' 18 | runtime='dotnet' 19 | runtimeSourceFeed='' 20 | runtimeSourceFeedKey='' 21 | while [[ $# > 0 ]]; do 22 | opt="$(echo "$1" | tr "[:upper:]" "[:lower:]")" 23 | case "$opt" in 24 | -version|-v) 25 | shift 26 | version="$1" 27 | ;; 28 | -architecture|-a) 29 | shift 30 | architecture="$1" 31 | ;; 32 | -runtime|-r) 33 | shift 34 | runtime="$1" 35 | ;; 36 | -runtimesourcefeed) 37 | shift 38 | runtimeSourceFeed="$1" 39 | ;; 40 | -runtimesourcefeedkey) 41 | shift 42 | runtimeSourceFeedKey="$1" 43 | ;; 44 | *) 45 | Write-PipelineTelemetryError -Category 'Build' -Message "Invalid argument: $1" 46 | exit 1 47 | ;; 48 | esac 49 | shift 50 | done 51 | 52 | # Use uname to determine what the CPU is, see https://en.wikipedia.org/wiki/Uname#Examples 53 | cpuname=$(uname -m) 54 | case $cpuname in 55 | arm64|aarch64) 56 | buildarch=arm64 57 | if [ "$(getconf LONG_BIT)" -lt 64 ]; then 58 | # This is 32-bit OS running on 64-bit CPU (for example Raspberry Pi OS) 59 | buildarch=arm 60 | fi 61 | ;; 62 | loongarch64) 63 | buildarch=loongarch64 64 | ;; 65 | amd64|x86_64) 66 | buildarch=x64 67 | ;; 68 | armv*l) 69 | buildarch=arm 70 | ;; 71 | i[3-6]86) 72 | buildarch=x86 73 | ;; 74 | riscv64) 75 | buildarch=riscv64 76 | ;; 77 | *) 78 | echo "Unknown CPU $cpuname detected, treating it as x64" 79 | buildarch=x64 80 | ;; 81 | esac 82 | 83 | dotnetRoot="${repo_root}.dotnet" 84 | if [[ $architecture != "" ]] && [[ $architecture != $buildarch ]]; then 85 | dotnetRoot="$dotnetRoot/$architecture" 86 | fi 87 | 88 | InstallDotNet "$dotnetRoot" $version "$architecture" $runtime true $runtimeSourceFeed $runtimeSourceFeedKey || { 89 | local exit_code=$? 90 | Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "dotnet-install.sh failed (exit code '$exit_code')." >&2 91 | ExitWithExitCode $exit_code 92 | } 93 | 94 | ExitWithExitCode 0 95 | -------------------------------------------------------------------------------- /eng/common/enable-cross-org-publishing.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [string] $token 3 | ) 4 | 5 | 6 | . $PSScriptRoot\pipeline-logging-functions.ps1 7 | 8 | # Write-PipelineSetVariable will no-op if a variable named $ci is not defined 9 | # Since this script is only ever called in AzDO builds, just universally set it 10 | $ci = $true 11 | 12 | Write-PipelineSetVariable -Name 'VSS_NUGET_ACCESSTOKEN' -Value $token -IsMultiJobVariable $false 13 | Write-PipelineSetVariable -Name 'VSS_NUGET_URI_PREFIXES' -Value 'https://dnceng.pkgs.visualstudio.com/;https://pkgs.dev.azure.com/dnceng/;https://devdiv.pkgs.visualstudio.com/;https://pkgs.dev.azure.com/devdiv/' -IsMultiJobVariable $false 14 | -------------------------------------------------------------------------------- /eng/common/generate-sbom-prep.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(Mandatory=$true)][string] $ManifestDirPath # Manifest directory where sbom will be placed 3 | ) 4 | 5 | . $PSScriptRoot\pipeline-logging-functions.ps1 6 | 7 | Write-Host "Creating dir $ManifestDirPath" 8 | # create directory for sbom manifest to be placed 9 | if (!(Test-Path -path $ManifestDirPath)) 10 | { 11 | New-Item -ItemType Directory -path $ManifestDirPath 12 | Write-Host "Successfully created directory $ManifestDirPath" 13 | } 14 | else{ 15 | Write-PipelineTelemetryError -category 'Build' "Unable to create sbom folder." 16 | } 17 | 18 | Write-Host "Updating artifact name" 19 | $artifact_name = "${env:SYSTEM_STAGENAME}_${env:AGENT_JOBNAME}_SBOM" -replace '["/:<>\\|?@*"() ]', '_' 20 | Write-Host "Artifact name $artifact_name" 21 | Write-Host "##vso[task.setvariable variable=ARTIFACT_NAME]$artifact_name" 22 | -------------------------------------------------------------------------------- /eng/common/generate-sbom-prep.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | 5 | # resolve $SOURCE until the file is no longer a symlink 6 | while [[ -h $source ]]; do 7 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 8 | source="$(readlink "$source")" 9 | 10 | # if $source was a relative symlink, we need to resolve it relative to the path where the 11 | # symlink file was located 12 | [[ $source != /* ]] && source="$scriptroot/$source" 13 | done 14 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 15 | . $scriptroot/pipeline-logging-functions.sh 16 | 17 | manifest_dir=$1 18 | 19 | if [ ! -d "$manifest_dir" ] ; then 20 | mkdir -p "$manifest_dir" 21 | echo "Sbom directory created." $manifest_dir 22 | else 23 | Write-PipelineTelemetryError -category 'Build' "Unable to create sbom folder." 24 | fi 25 | 26 | artifact_name=$SYSTEM_STAGENAME"_"$AGENT_JOBNAME"_SBOM" 27 | echo "Artifact name before : "$artifact_name 28 | # replace all special characters with _, some builds use special characters like : in Agent.Jobname, that is not a permissible name while uploading artifacts. 29 | safe_artifact_name="${artifact_name//["/:<>\\|?@*$" ]/_}" 30 | echo "Artifact name after : "$safe_artifact_name 31 | export ARTIFACT_NAME=$safe_artifact_name 32 | echo "##vso[task.setvariable variable=ARTIFACT_NAME]$safe_artifact_name" 33 | 34 | exit 0 35 | -------------------------------------------------------------------------------- /eng/common/helixpublish.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | msbuild 6 | 7 | 8 | 9 | 10 | %(Identity) 11 | 12 | 13 | 14 | 15 | 16 | $(WorkItemDirectory) 17 | $(WorkItemCommand) 18 | $(WorkItemTimeout) 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /eng/common/init-tools-native.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -NoProfile -NoLogo -ExecutionPolicy ByPass -command "& """%~dp0init-tools-native.ps1""" %*" 3 | exit /b %ErrorLevel% -------------------------------------------------------------------------------- /eng/common/internal-feed-operations.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory=$true)][string] $Operation, 3 | [string] $AuthToken, 4 | [string] $CommitSha, 5 | [string] $RepoName, 6 | [switch] $IsFeedPrivate 7 | ) 8 | 9 | $ErrorActionPreference = 'Stop' 10 | Set-StrictMode -Version 2.0 11 | . $PSScriptRoot\tools.ps1 12 | 13 | # Sets VSS_NUGET_EXTERNAL_FEED_ENDPOINTS based on the "darc-int-*" feeds defined in NuGet.config. This is needed 14 | # in build agents by CredProvider to authenticate the restore requests to internal feeds as specified in 15 | # https://github.com/microsoft/artifacts-credprovider/blob/0f53327cd12fd893d8627d7b08a2171bf5852a41/README.md#environment-variables. This should ONLY be called from identified 16 | # internal builds 17 | function SetupCredProvider { 18 | param( 19 | [string] $AuthToken 20 | ) 21 | 22 | # Install the Cred Provider NuGet plugin 23 | Write-Host 'Setting up Cred Provider NuGet plugin in the agent...' 24 | Write-Host "Getting 'installcredprovider.ps1' from 'https://github.com/microsoft/artifacts-credprovider'..." 25 | 26 | $url = 'https://raw.githubusercontent.com/microsoft/artifacts-credprovider/master/helpers/installcredprovider.ps1' 27 | 28 | Write-Host "Writing the contents of 'installcredprovider.ps1' locally..." 29 | Invoke-WebRequest $url -OutFile installcredprovider.ps1 30 | 31 | Write-Host 'Installing plugin...' 32 | .\installcredprovider.ps1 -Force 33 | 34 | Write-Host "Deleting local copy of 'installcredprovider.ps1'..." 35 | Remove-Item .\installcredprovider.ps1 36 | 37 | if (-Not("$env:USERPROFILE\.nuget\plugins\netcore")) { 38 | Write-PipelineTelemetryError -Category 'Arcade' -Message 'CredProvider plugin was not installed correctly!' 39 | ExitWithExitCode 1 40 | } 41 | else { 42 | Write-Host 'CredProvider plugin was installed correctly!' 43 | } 44 | 45 | # Then, we set the 'VSS_NUGET_EXTERNAL_FEED_ENDPOINTS' environment variable to restore from the stable 46 | # feeds successfully 47 | 48 | $nugetConfigPath = Join-Path $RepoRoot "NuGet.config" 49 | 50 | if (-Not (Test-Path -Path $nugetConfigPath)) { 51 | Write-PipelineTelemetryError -Category 'Build' -Message 'NuGet.config file not found in repo root!' 52 | ExitWithExitCode 1 53 | } 54 | 55 | $endpoints = New-Object System.Collections.ArrayList 56 | $nugetConfigPackageSources = Select-Xml -Path $nugetConfigPath -XPath "//packageSources/add[contains(@key, 'darc-int-')]/@value" | foreach{$_.Node.Value} 57 | 58 | if (($nugetConfigPackageSources | Measure-Object).Count -gt 0 ) { 59 | foreach ($stableRestoreResource in $nugetConfigPackageSources) { 60 | $trimmedResource = ([string]$stableRestoreResource).Trim() 61 | [void]$endpoints.Add(@{endpoint="$trimmedResource"; password="$AuthToken"}) 62 | } 63 | } 64 | 65 | if (($endpoints | Measure-Object).Count -gt 0) { 66 | $endpointCredentials = @{endpointCredentials=$endpoints} | ConvertTo-Json -Compress 67 | 68 | # Create the environment variables the AzDo way 69 | Write-LoggingCommand -Area 'task' -Event 'setvariable' -Data $endpointCredentials -Properties @{ 70 | 'variable' = 'VSS_NUGET_EXTERNAL_FEED_ENDPOINTS' 71 | 'issecret' = 'false' 72 | } 73 | 74 | # We don't want sessions cached since we will be updating the endpoints quite frequently 75 | Write-LoggingCommand -Area 'task' -Event 'setvariable' -Data 'False' -Properties @{ 76 | 'variable' = 'NUGET_CREDENTIALPROVIDER_SESSIONTOKENCACHE_ENABLED' 77 | 'issecret' = 'false' 78 | } 79 | } 80 | else 81 | { 82 | Write-Host 'No internal endpoints found in NuGet.config' 83 | } 84 | } 85 | 86 | #Workaround for https://github.com/microsoft/msbuild/issues/4430 87 | function InstallDotNetSdkAndRestoreArcade { 88 | $dotnetTempDir = Join-Path $RepoRoot "dotnet" 89 | $dotnetSdkVersion="2.1.507" # After experimentation we know this version works when restoring the SDK (compared to 3.0.*) 90 | $dotnet = "$dotnetTempDir\dotnet.exe" 91 | $restoreProjPath = "$PSScriptRoot\restore.proj" 92 | 93 | Write-Host "Installing dotnet SDK version $dotnetSdkVersion to restore Arcade SDK..." 94 | InstallDotNetSdk "$dotnetTempDir" "$dotnetSdkVersion" 95 | 96 | '' | Out-File "$restoreProjPath" 97 | 98 | & $dotnet restore $restoreProjPath 99 | 100 | Write-Host 'Arcade SDK restored!' 101 | 102 | if (Test-Path -Path $restoreProjPath) { 103 | Remove-Item $restoreProjPath 104 | } 105 | 106 | if (Test-Path -Path $dotnetTempDir) { 107 | Remove-Item $dotnetTempDir -Recurse 108 | } 109 | } 110 | 111 | try { 112 | Push-Location $PSScriptRoot 113 | 114 | if ($Operation -like 'setup') { 115 | SetupCredProvider $AuthToken 116 | } 117 | elseif ($Operation -like 'install-restore') { 118 | InstallDotNetSdkAndRestoreArcade 119 | } 120 | else { 121 | Write-PipelineTelemetryError -Category 'Arcade' -Message "Unknown operation '$Operation'!" 122 | ExitWithExitCode 1 123 | } 124 | } 125 | catch { 126 | Write-Host $_.ScriptStackTrace 127 | Write-PipelineTelemetryError -Category 'Arcade' -Message $_ 128 | ExitWithExitCode 1 129 | } 130 | finally { 131 | Pop-Location 132 | } 133 | -------------------------------------------------------------------------------- /eng/common/internal-feed-operations.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | # Sets VSS_NUGET_EXTERNAL_FEED_ENDPOINTS based on the "darc-int-*" feeds defined in NuGet.config. This is needed 6 | # in build agents by CredProvider to authenticate the restore requests to internal feeds as specified in 7 | # https://github.com/microsoft/artifacts-credprovider/blob/0f53327cd12fd893d8627d7b08a2171bf5852a41/README.md#environment-variables. 8 | # This should ONLY be called from identified internal builds 9 | function SetupCredProvider { 10 | local authToken=$1 11 | 12 | # Install the Cred Provider NuGet plugin 13 | echo "Setting up Cred Provider NuGet plugin in the agent..."... 14 | echo "Getting 'installcredprovider.ps1' from 'https://github.com/microsoft/artifacts-credprovider'..." 15 | 16 | local url="https://raw.githubusercontent.com/microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh" 17 | 18 | echo "Writing the contents of 'installcredprovider.ps1' locally..." 19 | local installcredproviderPath="installcredprovider.sh" 20 | if command -v curl > /dev/null; then 21 | curl $url > "$installcredproviderPath" 22 | else 23 | wget -q -O "$installcredproviderPath" "$url" 24 | fi 25 | 26 | echo "Installing plugin..." 27 | . "$installcredproviderPath" 28 | 29 | echo "Deleting local copy of 'installcredprovider.sh'..." 30 | rm installcredprovider.sh 31 | 32 | if [ ! -d "$HOME/.nuget/plugins" ]; then 33 | Write-PipelineTelemetryError -category 'Build' 'CredProvider plugin was not installed correctly!' 34 | ExitWithExitCode 1 35 | else 36 | echo "CredProvider plugin was installed correctly!" 37 | fi 38 | 39 | # Then, we set the 'VSS_NUGET_EXTERNAL_FEED_ENDPOINTS' environment variable to restore from the stable 40 | # feeds successfully 41 | 42 | local nugetConfigPath="{$repo_root}NuGet.config" 43 | 44 | if [ ! "$nugetConfigPath" ]; then 45 | Write-PipelineTelemetryError -category 'Build' "NuGet.config file not found in repo's root!" 46 | ExitWithExitCode 1 47 | fi 48 | 49 | local endpoints='[' 50 | local nugetConfigPackageValues=`cat "$nugetConfigPath" | grep "key=\"darc-int-"` 51 | local pattern="value=\"(.*)\"" 52 | 53 | for value in $nugetConfigPackageValues 54 | do 55 | if [[ $value =~ $pattern ]]; then 56 | local endpoint="${BASH_REMATCH[1]}" 57 | endpoints+="{\"endpoint\": \"$endpoint\", \"password\": \"$authToken\"}," 58 | fi 59 | done 60 | 61 | endpoints=${endpoints%?} 62 | endpoints+=']' 63 | 64 | if [ ${#endpoints} -gt 2 ]; then 65 | local endpointCredentials="{\"endpointCredentials\": "$endpoints"}" 66 | 67 | echo "##vso[task.setvariable variable=VSS_NUGET_EXTERNAL_FEED_ENDPOINTS]$endpointCredentials" 68 | echo "##vso[task.setvariable variable=NUGET_CREDENTIALPROVIDER_SESSIONTOKENCACHE_ENABLED]False" 69 | else 70 | echo "No internal endpoints found in NuGet.config" 71 | fi 72 | } 73 | 74 | # Workaround for https://github.com/microsoft/msbuild/issues/4430 75 | function InstallDotNetSdkAndRestoreArcade { 76 | local dotnetTempDir="$repo_root/dotnet" 77 | local dotnetSdkVersion="2.1.507" # After experimentation we know this version works when restoring the SDK (compared to 3.0.*) 78 | local restoreProjPath="$repo_root/eng/common/restore.proj" 79 | 80 | echo "Installing dotnet SDK version $dotnetSdkVersion to restore Arcade SDK..." 81 | echo "" > "$restoreProjPath" 82 | 83 | InstallDotNetSdk "$dotnetTempDir" "$dotnetSdkVersion" 84 | 85 | local res=`$dotnetTempDir/dotnet restore $restoreProjPath` 86 | echo "Arcade SDK restored!" 87 | 88 | # Cleanup 89 | if [ "$restoreProjPath" ]; then 90 | rm "$restoreProjPath" 91 | fi 92 | 93 | if [ "$dotnetTempDir" ]; then 94 | rm -r $dotnetTempDir 95 | fi 96 | } 97 | 98 | source="${BASH_SOURCE[0]}" 99 | operation='' 100 | authToken='' 101 | repoName='' 102 | 103 | while [[ $# > 0 ]]; do 104 | opt="$(echo "$1" | tr "[:upper:]" "[:lower:]")" 105 | case "$opt" in 106 | --operation) 107 | operation=$2 108 | shift 109 | ;; 110 | --authtoken) 111 | authToken=$2 112 | shift 113 | ;; 114 | *) 115 | echo "Invalid argument: $1" 116 | usage 117 | exit 1 118 | ;; 119 | esac 120 | 121 | shift 122 | done 123 | 124 | while [[ -h "$source" ]]; do 125 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 126 | source="$(readlink "$source")" 127 | # if $source was a relative symlink, we need to resolve it relative to the path where the 128 | # symlink file was located 129 | [[ $source != /* ]] && source="$scriptroot/$source" 130 | done 131 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 132 | 133 | . "$scriptroot/tools.sh" 134 | 135 | if [ "$operation" = "setup" ]; then 136 | SetupCredProvider $authToken 137 | elif [ "$operation" = "install-restore" ]; then 138 | InstallDotNetSdkAndRestoreArcade 139 | else 140 | echo "Unknown operation '$operation'!" 141 | fi 142 | -------------------------------------------------------------------------------- /eng/common/internal/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | false 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /eng/common/internal/NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /eng/common/internal/Tools.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net472 6 | false 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | https://devdiv.pkgs.visualstudio.com/_packaging/dotnet-core-internal-tooling/nuget/v3/index.json; 22 | 23 | 24 | $(RestoreSources); 25 | https://devdiv.pkgs.visualstudio.com/_packaging/VS/nuget/v3/index.json; 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /eng/common/loc/P22DotNetHtmlLocalization.lss: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /eng/common/msbuild.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding(PositionalBinding=$false)] 2 | Param( 3 | [string] $verbosity = 'minimal', 4 | [bool] $warnAsError = $true, 5 | [bool] $nodeReuse = $true, 6 | [switch] $ci, 7 | [switch] $prepareMachine, 8 | [switch] $excludePrereleaseVS, 9 | [string] $msbuildEngine = $null, 10 | [Parameter(ValueFromRemainingArguments=$true)][String[]]$extraArgs 11 | ) 12 | 13 | . $PSScriptRoot\tools.ps1 14 | 15 | try { 16 | if ($ci) { 17 | $nodeReuse = $false 18 | } 19 | 20 | MSBuild @extraArgs 21 | } 22 | catch { 23 | Write-Host $_.ScriptStackTrace 24 | Write-PipelineTelemetryError -Category 'Build' -Message $_ 25 | ExitWithExitCode 1 26 | } 27 | 28 | ExitWithExitCode 0 -------------------------------------------------------------------------------- /eng/common/msbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | 5 | # resolve $source until the file is no longer a symlink 6 | while [[ -h "$source" ]]; do 7 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 8 | source="$(readlink "$source")" 9 | # if $source was a relative symlink, we need to resolve it relative to the path where the 10 | # symlink file was located 11 | [[ $source != /* ]] && source="$scriptroot/$source" 12 | done 13 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 14 | 15 | verbosity='minimal' 16 | warn_as_error=true 17 | node_reuse=true 18 | prepare_machine=false 19 | extra_args='' 20 | 21 | while (($# > 0)); do 22 | lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" 23 | case $lowerI in 24 | --verbosity) 25 | verbosity=$2 26 | shift 2 27 | ;; 28 | --warnaserror) 29 | warn_as_error=$2 30 | shift 2 31 | ;; 32 | --nodereuse) 33 | node_reuse=$2 34 | shift 2 35 | ;; 36 | --ci) 37 | ci=true 38 | shift 1 39 | ;; 40 | --preparemachine) 41 | prepare_machine=true 42 | shift 1 43 | ;; 44 | *) 45 | extra_args="$extra_args $1" 46 | shift 1 47 | ;; 48 | esac 49 | done 50 | 51 | . "$scriptroot/tools.sh" 52 | 53 | if [[ "$ci" == true ]]; then 54 | node_reuse=false 55 | fi 56 | 57 | MSBuild $extra_args 58 | ExitWithExitCode 0 59 | -------------------------------------------------------------------------------- /eng/common/native/common-library.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function GetNativeInstallDirectory { 4 | local install_dir 5 | 6 | if [[ -z $NETCOREENG_INSTALL_DIRECTORY ]]; then 7 | install_dir=$HOME/.netcoreeng/native/ 8 | else 9 | install_dir=$NETCOREENG_INSTALL_DIRECTORY 10 | fi 11 | 12 | echo $install_dir 13 | return 0 14 | } 15 | 16 | function GetTempDirectory { 17 | 18 | echo $(GetNativeInstallDirectory)temp/ 19 | return 0 20 | } 21 | 22 | function ExpandZip { 23 | local zip_path=$1 24 | local output_directory=$2 25 | local force=${3:-false} 26 | 27 | echo "Extracting $zip_path to $output_directory" 28 | if [[ -d $output_directory ]] && [[ $force = false ]]; then 29 | echo "Directory '$output_directory' already exists, skipping extract" 30 | return 0 31 | fi 32 | 33 | if [[ -d $output_directory ]]; then 34 | echo "'Force flag enabled, but '$output_directory' exists. Removing directory" 35 | rm -rf $output_directory 36 | if [[ $? != 0 ]]; then 37 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' "Unable to remove '$output_directory'" 38 | return 1 39 | fi 40 | fi 41 | 42 | echo "Creating directory: '$output_directory'" 43 | mkdir -p $output_directory 44 | 45 | echo "Extracting archive" 46 | tar -xf $zip_path -C $output_directory 47 | if [[ $? != 0 ]]; then 48 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' "Unable to extract '$zip_path'" 49 | return 1 50 | fi 51 | 52 | return 0 53 | } 54 | 55 | function GetCurrentOS { 56 | local unameOut="$(uname -s)" 57 | case $unameOut in 58 | Linux*) echo "Linux";; 59 | Darwin*) echo "MacOS";; 60 | esac 61 | return 0 62 | } 63 | 64 | function GetFile { 65 | local uri=$1 66 | local path=$2 67 | local force=${3:-false} 68 | local download_retries=${4:-5} 69 | local retry_wait_time_seconds=${5:-30} 70 | 71 | if [[ -f $path ]]; then 72 | if [[ $force = false ]]; then 73 | echo "File '$path' already exists. Skipping download" 74 | return 0 75 | else 76 | rm -rf $path 77 | fi 78 | fi 79 | 80 | if [[ -f $uri ]]; then 81 | echo "'$uri' is a file path, copying file to '$path'" 82 | cp $uri $path 83 | return $? 84 | fi 85 | 86 | echo "Downloading $uri" 87 | # Use curl if available, otherwise use wget 88 | if command -v curl > /dev/null; then 89 | curl "$uri" -sSL --retry $download_retries --retry-delay $retry_wait_time_seconds --create-dirs -o "$path" --fail 90 | else 91 | wget -q -O "$path" "$uri" --tries="$download_retries" 92 | fi 93 | 94 | return $? 95 | } 96 | 97 | function GetTempPathFileName { 98 | local path=$1 99 | 100 | local temp_dir=$(GetTempDirectory) 101 | local temp_file_name=$(basename $path) 102 | echo $temp_dir$temp_file_name 103 | return 0 104 | } 105 | 106 | function DownloadAndExtract { 107 | local uri=$1 108 | local installDir=$2 109 | local force=${3:-false} 110 | local download_retries=${4:-5} 111 | local retry_wait_time_seconds=${5:-30} 112 | 113 | local temp_tool_path=$(GetTempPathFileName $uri) 114 | 115 | echo "downloading to: $temp_tool_path" 116 | 117 | # Download file 118 | GetFile "$uri" "$temp_tool_path" $force $download_retries $retry_wait_time_seconds 119 | if [[ $? != 0 ]]; then 120 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' "Failed to download '$uri' to '$temp_tool_path'." 121 | return 1 122 | fi 123 | 124 | # Extract File 125 | echo "extracting from $temp_tool_path to $installDir" 126 | ExpandZip "$temp_tool_path" "$installDir" $force $download_retries $retry_wait_time_seconds 127 | if [[ $? != 0 ]]; then 128 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' "Failed to extract '$temp_tool_path' to '$installDir'." 129 | return 1 130 | fi 131 | 132 | return 0 133 | } 134 | 135 | function NewScriptShim { 136 | local shimpath=$1 137 | local tool_file_path=$2 138 | local force=${3:-false} 139 | 140 | echo "Generating '$shimpath' shim" 141 | if [[ -f $shimpath ]]; then 142 | if [[ $force = false ]]; then 143 | echo "File '$shimpath' already exists." >&2 144 | return 1 145 | else 146 | rm -rf $shimpath 147 | fi 148 | fi 149 | 150 | if [[ ! -f $tool_file_path ]]; then 151 | # try to see if the path is lower cased 152 | tool_file_path="$(echo $tool_file_path | tr "[:upper:]" "[:lower:]")" 153 | if [[ ! -f $tool_file_path ]]; then 154 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' "Specified tool file path:'$tool_file_path' does not exist" 155 | return 1 156 | fi 157 | fi 158 | 159 | local shim_contents=$'#!/usr/bin/env bash\n' 160 | shim_contents+="SHIMARGS="$'$1\n' 161 | shim_contents+="$tool_file_path"$' $SHIMARGS\n' 162 | 163 | # Write shim file 164 | echo "$shim_contents" > $shimpath 165 | 166 | chmod +x $shimpath 167 | 168 | echo "Finished generating shim '$shimpath'" 169 | 170 | return $? 171 | } 172 | 173 | -------------------------------------------------------------------------------- /eng/common/native/init-compiler.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This file detects the C/C++ compiler and exports it to the CC/CXX environment variables 4 | # 5 | # NOTE: some scripts source this file and rely on stdout being empty, make sure 6 | # to not output *anything* here, unless it is an error message that fails the 7 | # build. 8 | 9 | if [ -z "$build_arch" ] || [ -z "$compiler" ]; then 10 | echo "Usage..." 11 | echo "build_arch= compiler= init-compiler.sh" 12 | echo "Specify the target architecture." 13 | echo "Specify the name of compiler (clang or gcc)." 14 | exit 1 15 | fi 16 | 17 | case "$compiler" in 18 | clang*|-clang*|--clang*) 19 | # clangx.y or clang-x.y 20 | version="$(echo "$compiler" | tr -d '[:alpha:]-=')" 21 | majorVersion="${version%%.*}" 22 | 23 | # LLVM based on v18 released in early 2024, with two releases per year 24 | maxVersion="$((18 + ((($(date +%Y) - 2024) * 12 + $(date +%-m) - 3) / 6)))" 25 | compiler=clang 26 | ;; 27 | 28 | gcc*|-gcc*|--gcc*) 29 | # gccx.y or gcc-x.y 30 | version="$(echo "$compiler" | tr -d '[:alpha:]-=')" 31 | majorVersion="${version%%.*}" 32 | 33 | # GCC based on v14 released in early 2024, with one release per year 34 | maxVersion="$((14 + ((($(date +%Y) - 2024) * 12 + $(date +%-m) - 3) / 12)))" 35 | compiler=gcc 36 | ;; 37 | esac 38 | 39 | cxxCompiler="$compiler++" 40 | 41 | # clear the existing CC and CXX from environment 42 | CC= 43 | CXX= 44 | LDFLAGS= 45 | 46 | if [ "$compiler" = "gcc" ]; then cxxCompiler="g++"; fi 47 | 48 | check_version_exists() { 49 | desired_version=-1 50 | 51 | # Set up the environment to be used for building with the desired compiler. 52 | if command -v "$compiler-$1" > /dev/null; then 53 | desired_version="-$1" 54 | elif command -v "$compiler$1" > /dev/null; then 55 | desired_version="$1" 56 | fi 57 | 58 | echo "$desired_version" 59 | } 60 | 61 | __baseOS="$(uname)" 62 | set_compiler_version_from_CC() { 63 | if [ "$__baseOS" = "Darwin" ]; then 64 | # On Darwin, the versions from -version/-dumpversion refer to Xcode 65 | # versions, not llvm versions, so we can't rely on them. 66 | return 67 | fi 68 | 69 | version="$("$CC" -dumpversion)" 70 | if [ -z "$version" ]; then 71 | echo "Error: $CC -dumpversion didn't provide a version" 72 | exit 1 73 | fi 74 | 75 | # gcc and clang often display 3 part versions. However, gcc can show only 1 part in some environments. 76 | IFS=. read -r majorVersion _ < /dev/null; then 96 | echo "Error: No compatible version of $compiler was found within the range of $minVersion to $maxVersion. Please upgrade your toolchain or specify the compiler explicitly using CLR_CC and CLR_CXX environment variables." 97 | exit 1 98 | fi 99 | 100 | CC="$(command -v "$compiler" 2> /dev/null)" 101 | CXX="$(command -v "$cxxCompiler" 2> /dev/null)" 102 | set_compiler_version_from_CC 103 | fi 104 | else 105 | desired_version="$(check_version_exists "$majorVersion")" 106 | if [ "$desired_version" = "-1" ]; then 107 | echo "Error: Could not find specific version of $compiler: $majorVersion." 108 | exit 1 109 | fi 110 | fi 111 | 112 | if [ -z "$CC" ]; then 113 | CC="$(command -v "$compiler$desired_version" 2> /dev/null)" 114 | CXX="$(command -v "$cxxCompiler$desired_version" 2> /dev/null)" 115 | if [ -z "$CXX" ]; then CXX="$(command -v "$cxxCompiler" 2> /dev/null)"; fi 116 | set_compiler_version_from_CC 117 | fi 118 | else 119 | if [ ! -f "$CLR_CC" ]; then 120 | echo "Error: CLR_CC is set but path '$CLR_CC' does not exist" 121 | exit 1 122 | fi 123 | CC="$CLR_CC" 124 | CXX="$CLR_CXX" 125 | set_compiler_version_from_CC 126 | fi 127 | 128 | if [ -z "$CC" ]; then 129 | echo "Error: Unable to find $compiler." 130 | exit 1 131 | fi 132 | 133 | if [ "$__baseOS" != "Darwin" ]; then 134 | # On Darwin, we always want to use the Apple linker. 135 | 136 | # Only lld version >= 9 can be considered stable. lld supports s390x starting from 18.0. 137 | if [ "$compiler" = "clang" ] && [ -n "$majorVersion" ] && [ "$majorVersion" -ge 9 ] && { [ "$build_arch" != "s390x" ] || [ "$majorVersion" -ge 18 ]; }; then 138 | if "$CC" -fuse-ld=lld -Wl,--version >/dev/null 2>&1; then 139 | LDFLAGS="-fuse-ld=lld" 140 | fi 141 | fi 142 | fi 143 | 144 | SCAN_BUILD_COMMAND="$(command -v "scan-build$desired_version" 2> /dev/null)" 145 | 146 | export CC CXX LDFLAGS SCAN_BUILD_COMMAND 147 | -------------------------------------------------------------------------------- /eng/common/native/init-distro-rid.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # getNonPortableDistroRid 4 | # 5 | # Input: 6 | # targetOs: (str) 7 | # targetArch: (str) 8 | # rootfsDir: (str) 9 | # 10 | # Return: 11 | # non-portable rid 12 | getNonPortableDistroRid() 13 | { 14 | targetOs="$1" 15 | targetArch="$2" 16 | rootfsDir="$3" 17 | nonPortableRid="" 18 | 19 | if [ "$targetOs" = "linux" ]; then 20 | # shellcheck disable=SC1091 21 | if [ -e "${rootfsDir}/etc/os-release" ]; then 22 | . "${rootfsDir}/etc/os-release" 23 | if echo "${VERSION_ID:-}" | grep -qE '^([[:digit:]]|\.)+$'; then 24 | nonPortableRid="${ID}.${VERSION_ID}-${targetArch}" 25 | else 26 | # Rolling release distros either do not set VERSION_ID, set it as blank or 27 | # set it to non-version looking string (such as TEMPLATE_VERSION_ID on ArchLinux); 28 | # so omit it here to be consistent with everything else. 29 | nonPortableRid="${ID}-${targetArch}" 30 | fi 31 | elif [ -e "${rootfsDir}/android_platform" ]; then 32 | # shellcheck disable=SC1091 33 | . "${rootfsDir}/android_platform" 34 | nonPortableRid="$RID" 35 | fi 36 | fi 37 | 38 | if [ "$targetOs" = "freebsd" ]; then 39 | # $rootfsDir can be empty. freebsd-version is a shell script and should always work. 40 | __freebsd_major_version=$("$rootfsDir"/bin/freebsd-version | cut -d'.' -f1) 41 | nonPortableRid="freebsd.$__freebsd_major_version-${targetArch}" 42 | elif command -v getprop >/dev/null && getprop ro.product.system.model | grep -qi android; then 43 | __android_sdk_version=$(getprop ro.build.version.sdk) 44 | nonPortableRid="android.$__android_sdk_version-${targetArch}" 45 | elif [ "$targetOs" = "illumos" ]; then 46 | __uname_version=$(uname -v) 47 | nonPortableRid="illumos-${targetArch}" 48 | elif [ "$targetOs" = "solaris" ]; then 49 | __uname_version=$(uname -v) 50 | __solaris_major_version=$(echo "$__uname_version" | cut -d'.' -f1) 51 | nonPortableRid="solaris.$__solaris_major_version-${targetArch}" 52 | elif [ "$targetOs" = "haiku" ]; then 53 | __uname_release="$(uname -r)" 54 | nonPortableRid=haiku.r"$__uname_release"-"$targetArch" 55 | fi 56 | 57 | echo "$nonPortableRid" | tr '[:upper:]' '[:lower:]' 58 | } 59 | 60 | # initDistroRidGlobal 61 | # 62 | # Input: 63 | # os: (str) 64 | # arch: (str) 65 | # rootfsDir?: (nullable:string) 66 | # 67 | # Return: 68 | # None 69 | # 70 | # Notes: 71 | # It is important to note that the function does not return anything, but it 72 | # exports the following variables on success: 73 | # __DistroRid : Non-portable rid of the target platform. 74 | # __PortableTargetOS : OS-part of the portable rid that corresponds to the target platform. 75 | initDistroRidGlobal() 76 | { 77 | targetOs="$1" 78 | targetArch="$2" 79 | rootfsDir="" 80 | if [ $# -ge 3 ]; then 81 | rootfsDir="$3" 82 | fi 83 | 84 | if [ -n "${rootfsDir}" ]; then 85 | # We may have a cross build. Check for the existence of the rootfsDir 86 | if [ ! -e "${rootfsDir}" ]; then 87 | echo "Error: rootfsDir has been passed, but the location is not valid." 88 | exit 1 89 | fi 90 | fi 91 | 92 | __DistroRid=$(getNonPortableDistroRid "${targetOs}" "${targetArch}" "${rootfsDir}") 93 | 94 | if [ -z "${__PortableTargetOS:-}" ]; then 95 | __PortableTargetOS="$targetOs" 96 | 97 | STRINGS="$(command -v strings || true)" 98 | if [ -z "$STRINGS" ]; then 99 | STRINGS="$(command -v llvm-strings || true)" 100 | fi 101 | 102 | # Check for musl-based distros (e.g. Alpine Linux, Void Linux). 103 | if "${rootfsDir}/usr/bin/ldd" --version 2>&1 | grep -q musl || 104 | ( [ -n "$STRINGS" ] && "$STRINGS" "${rootfsDir}/usr/bin/ldd" 2>&1 | grep -q musl ); then 105 | __PortableTargetOS="linux-musl" 106 | fi 107 | fi 108 | 109 | export __DistroRid __PortableTargetOS 110 | } 111 | -------------------------------------------------------------------------------- /eng/common/native/init-os-and-arch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Use uname to determine what the OS is. 4 | OSName=$(uname -s | tr '[:upper:]' '[:lower:]') 5 | 6 | if command -v getprop && getprop ro.product.system.model 2>&1 | grep -qi android; then 7 | OSName="android" 8 | fi 9 | 10 | case "$OSName" in 11 | freebsd|linux|netbsd|openbsd|sunos|android|haiku) 12 | os="$OSName" ;; 13 | darwin) 14 | os=osx ;; 15 | *) 16 | echo "Unsupported OS $OSName detected!" 17 | exit 1 ;; 18 | esac 19 | 20 | # On Solaris, `uname -m` is discouraged, see https://docs.oracle.com/cd/E36784_01/html/E36870/uname-1.html 21 | # and `uname -p` returns processor type (e.g. i386 on amd64). 22 | # The appropriate tool to determine CPU is isainfo(1) https://docs.oracle.com/cd/E36784_01/html/E36870/isainfo-1.html. 23 | if [ "$os" = "sunos" ]; then 24 | if uname -o 2>&1 | grep -q illumos; then 25 | os="illumos" 26 | else 27 | os="solaris" 28 | fi 29 | CPUName=$(isainfo -n) 30 | else 31 | # For the rest of the operating systems, use uname(1) to determine what the CPU is. 32 | CPUName=$(uname -m) 33 | fi 34 | 35 | case "$CPUName" in 36 | arm64|aarch64) 37 | arch=arm64 38 | if [ "$(getconf LONG_BIT)" -lt 64 ]; then 39 | # This is 32-bit OS running on 64-bit CPU (for example Raspberry Pi OS) 40 | arch=arm 41 | fi 42 | ;; 43 | 44 | loongarch64) 45 | arch=loongarch64 46 | ;; 47 | 48 | riscv64) 49 | arch=riscv64 50 | ;; 51 | 52 | amd64|x86_64) 53 | arch=x64 54 | ;; 55 | 56 | armv7l|armv8l) 57 | # shellcheck disable=SC1091 58 | if (NAME=""; . /etc/os-release; test "$NAME" = "Tizen"); then 59 | arch=armel 60 | else 61 | arch=arm 62 | fi 63 | ;; 64 | 65 | armv6l) 66 | arch=armv6 67 | ;; 68 | 69 | i[3-6]86) 70 | echo "Unsupported CPU $CPUName detected, build might not succeed!" 71 | arch=x86 72 | ;; 73 | 74 | s390x) 75 | arch=s390x 76 | ;; 77 | 78 | ppc64le) 79 | arch=ppc64le 80 | ;; 81 | *) 82 | echo "Unknown CPU $CPUName detected!" 83 | exit 1 84 | ;; 85 | esac 86 | -------------------------------------------------------------------------------- /eng/common/native/install-cmake-test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 5 | 6 | . $scriptroot/common-library.sh 7 | 8 | base_uri= 9 | install_path= 10 | version= 11 | clean=false 12 | force=false 13 | download_retries=5 14 | retry_wait_time_seconds=30 15 | 16 | while (($# > 0)); do 17 | lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" 18 | case $lowerI in 19 | --baseuri) 20 | base_uri=$2 21 | shift 2 22 | ;; 23 | --installpath) 24 | install_path=$2 25 | shift 2 26 | ;; 27 | --version) 28 | version=$2 29 | shift 2 30 | ;; 31 | --clean) 32 | clean=true 33 | shift 1 34 | ;; 35 | --force) 36 | force=true 37 | shift 1 38 | ;; 39 | --downloadretries) 40 | download_retries=$2 41 | shift 2 42 | ;; 43 | --retrywaittimeseconds) 44 | retry_wait_time_seconds=$2 45 | shift 2 46 | ;; 47 | --help) 48 | echo "Common settings:" 49 | echo " --baseuri Base file directory or Url wrom which to acquire tool archives" 50 | echo " --installpath Base directory to install native tool to" 51 | echo " --clean Don't install the tool, just clean up the current install of the tool" 52 | echo " --force Force install of tools even if they previously exist" 53 | echo " --help Print help and exit" 54 | echo "" 55 | echo "Advanced settings:" 56 | echo " --downloadretries Total number of retry attempts" 57 | echo " --retrywaittimeseconds Wait time between retry attempts in seconds" 58 | echo "" 59 | exit 0 60 | ;; 61 | esac 62 | done 63 | 64 | tool_name="cmake-test" 65 | tool_os=$(GetCurrentOS) 66 | tool_folder="$(echo $tool_os | tr "[:upper:]" "[:lower:]")" 67 | tool_arch="x86_64" 68 | tool_name_moniker="$tool_name-$version-$tool_os-$tool_arch" 69 | tool_install_directory="$install_path/$tool_name/$version" 70 | tool_file_path="$tool_install_directory/$tool_name_moniker/bin/$tool_name" 71 | shim_path="$install_path/$tool_name.sh" 72 | uri="${base_uri}/$tool_folder/$tool_name/$tool_name_moniker.tar.gz" 73 | 74 | # Clean up tool and installers 75 | if [[ $clean = true ]]; then 76 | echo "Cleaning $tool_install_directory" 77 | if [[ -d $tool_install_directory ]]; then 78 | rm -rf $tool_install_directory 79 | fi 80 | 81 | echo "Cleaning $shim_path" 82 | if [[ -f $shim_path ]]; then 83 | rm -rf $shim_path 84 | fi 85 | 86 | tool_temp_path=$(GetTempPathFileName $uri) 87 | echo "Cleaning $tool_temp_path" 88 | if [[ -f $tool_temp_path ]]; then 89 | rm -rf $tool_temp_path 90 | fi 91 | 92 | exit 0 93 | fi 94 | 95 | # Install tool 96 | if [[ -f $tool_file_path ]] && [[ $force = false ]]; then 97 | echo "$tool_name ($version) already exists, skipping install" 98 | exit 0 99 | fi 100 | 101 | DownloadAndExtract $uri $tool_install_directory $force $download_retries $retry_wait_time_seconds 102 | 103 | if [[ $? != 0 ]]; then 104 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' 'Installation failed' 105 | exit 1 106 | fi 107 | 108 | # Generate Shim 109 | # Always rewrite shims so that we are referencing the expected version 110 | NewScriptShim $shim_path $tool_file_path true 111 | 112 | if [[ $? != 0 ]]; then 113 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' 'Shim generation failed' 114 | exit 1 115 | fi 116 | 117 | exit 0 118 | -------------------------------------------------------------------------------- /eng/common/native/install-cmake.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 5 | 6 | . $scriptroot/common-library.sh 7 | 8 | base_uri= 9 | install_path= 10 | version= 11 | clean=false 12 | force=false 13 | download_retries=5 14 | retry_wait_time_seconds=30 15 | 16 | while (($# > 0)); do 17 | lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" 18 | case $lowerI in 19 | --baseuri) 20 | base_uri=$2 21 | shift 2 22 | ;; 23 | --installpath) 24 | install_path=$2 25 | shift 2 26 | ;; 27 | --version) 28 | version=$2 29 | shift 2 30 | ;; 31 | --clean) 32 | clean=true 33 | shift 1 34 | ;; 35 | --force) 36 | force=true 37 | shift 1 38 | ;; 39 | --downloadretries) 40 | download_retries=$2 41 | shift 2 42 | ;; 43 | --retrywaittimeseconds) 44 | retry_wait_time_seconds=$2 45 | shift 2 46 | ;; 47 | --help) 48 | echo "Common settings:" 49 | echo " --baseuri Base file directory or Url wrom which to acquire tool archives" 50 | echo " --installpath Base directory to install native tool to" 51 | echo " --clean Don't install the tool, just clean up the current install of the tool" 52 | echo " --force Force install of tools even if they previously exist" 53 | echo " --help Print help and exit" 54 | echo "" 55 | echo "Advanced settings:" 56 | echo " --downloadretries Total number of retry attempts" 57 | echo " --retrywaittimeseconds Wait time between retry attempts in seconds" 58 | echo "" 59 | exit 0 60 | ;; 61 | esac 62 | done 63 | 64 | tool_name="cmake" 65 | tool_os=$(GetCurrentOS) 66 | tool_folder="$(echo $tool_os | tr "[:upper:]" "[:lower:]")" 67 | tool_arch="x86_64" 68 | tool_name_moniker="$tool_name-$version-$tool_os-$tool_arch" 69 | tool_install_directory="$install_path/$tool_name/$version" 70 | tool_file_path="$tool_install_directory/$tool_name_moniker/bin/$tool_name" 71 | shim_path="$install_path/$tool_name.sh" 72 | uri="${base_uri}/$tool_folder/$tool_name/$tool_name_moniker.tar.gz" 73 | 74 | # Clean up tool and installers 75 | if [[ $clean = true ]]; then 76 | echo "Cleaning $tool_install_directory" 77 | if [[ -d $tool_install_directory ]]; then 78 | rm -rf $tool_install_directory 79 | fi 80 | 81 | echo "Cleaning $shim_path" 82 | if [[ -f $shim_path ]]; then 83 | rm -rf $shim_path 84 | fi 85 | 86 | tool_temp_path=$(GetTempPathFileName $uri) 87 | echo "Cleaning $tool_temp_path" 88 | if [[ -f $tool_temp_path ]]; then 89 | rm -rf $tool_temp_path 90 | fi 91 | 92 | exit 0 93 | fi 94 | 95 | # Install tool 96 | if [[ -f $tool_file_path ]] && [[ $force = false ]]; then 97 | echo "$tool_name ($version) already exists, skipping install" 98 | exit 0 99 | fi 100 | 101 | DownloadAndExtract $uri $tool_install_directory $force $download_retries $retry_wait_time_seconds 102 | 103 | if [[ $? != 0 ]]; then 104 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' 'Installation failed' 105 | exit 1 106 | fi 107 | 108 | # Generate Shim 109 | # Always rewrite shims so that we are referencing the expected version 110 | NewScriptShim $shim_path $tool_file_path true 111 | 112 | if [[ $? != 0 ]]; then 113 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' 'Shim generation failed' 114 | exit 1 115 | fi 116 | 117 | exit 0 118 | -------------------------------------------------------------------------------- /eng/common/native/install-tool.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Install native tool 4 | 5 | .DESCRIPTION 6 | Install cmake native tool from Azure blob storage 7 | 8 | .PARAMETER InstallPath 9 | Base directory to install native tool to 10 | 11 | .PARAMETER BaseUri 12 | Base file directory or Url from which to acquire tool archives 13 | 14 | .PARAMETER CommonLibraryDirectory 15 | Path to folder containing common library modules 16 | 17 | .PARAMETER Force 18 | Force install of tools even if they previously exist 19 | 20 | .PARAMETER Clean 21 | Don't install the tool, just clean up the current install of the tool 22 | 23 | .PARAMETER DownloadRetries 24 | Total number of retry attempts 25 | 26 | .PARAMETER RetryWaitTimeInSeconds 27 | Wait time between retry attempts in seconds 28 | 29 | .NOTES 30 | Returns 0 if install succeeds, 1 otherwise 31 | #> 32 | [CmdletBinding(PositionalBinding=$false)] 33 | Param ( 34 | [Parameter(Mandatory=$True)] 35 | [string] $ToolName, 36 | [Parameter(Mandatory=$True)] 37 | [string] $InstallPath, 38 | [Parameter(Mandatory=$True)] 39 | [string] $BaseUri, 40 | [Parameter(Mandatory=$True)] 41 | [string] $Version, 42 | [string] $CommonLibraryDirectory = $PSScriptRoot, 43 | [switch] $Force = $False, 44 | [switch] $Clean = $False, 45 | [int] $DownloadRetries = 5, 46 | [int] $RetryWaitTimeInSeconds = 30 47 | ) 48 | 49 | . $PSScriptRoot\..\pipeline-logging-functions.ps1 50 | 51 | # Import common library modules 52 | Import-Module -Name (Join-Path $CommonLibraryDirectory "CommonLibrary.psm1") 53 | 54 | try { 55 | # Define verbose switch if undefined 56 | $Verbose = $VerbosePreference -Eq "Continue" 57 | 58 | $Arch = CommonLibrary\Get-MachineArchitecture 59 | $ToolOs = "win64" 60 | if($Arch -Eq "x32") { 61 | $ToolOs = "win32" 62 | } 63 | $ToolNameMoniker = "$ToolName-$Version-$ToolOs-$Arch" 64 | $ToolInstallDirectory = Join-Path $InstallPath "$ToolName\$Version\" 65 | $Uri = "$BaseUri/windows/$ToolName/$ToolNameMoniker.zip" 66 | $ShimPath = Join-Path $InstallPath "$ToolName.exe" 67 | 68 | if ($Clean) { 69 | Write-Host "Cleaning $ToolInstallDirectory" 70 | if (Test-Path $ToolInstallDirectory) { 71 | Remove-Item $ToolInstallDirectory -Force -Recurse 72 | } 73 | Write-Host "Cleaning $ShimPath" 74 | if (Test-Path $ShimPath) { 75 | Remove-Item $ShimPath -Force 76 | } 77 | $ToolTempPath = CommonLibrary\Get-TempPathFilename -Path $Uri 78 | Write-Host "Cleaning $ToolTempPath" 79 | if (Test-Path $ToolTempPath) { 80 | Remove-Item $ToolTempPath -Force 81 | } 82 | exit 0 83 | } 84 | 85 | # Install tool 86 | if ((Test-Path $ToolInstallDirectory) -And (-Not $Force)) { 87 | Write-Verbose "$ToolName ($Version) already exists, skipping install" 88 | } 89 | else { 90 | $InstallStatus = CommonLibrary\DownloadAndExtract -Uri $Uri ` 91 | -InstallDirectory $ToolInstallDirectory ` 92 | -Force:$Force ` 93 | -DownloadRetries $DownloadRetries ` 94 | -RetryWaitTimeInSeconds $RetryWaitTimeInSeconds ` 95 | -Verbose:$Verbose 96 | 97 | if ($InstallStatus -Eq $False) { 98 | Write-PipelineTelemetryError "Installation failed" -Category "NativeToolsetBootstrapping" 99 | exit 1 100 | } 101 | } 102 | 103 | $ToolFilePath = Get-ChildItem $ToolInstallDirectory -Recurse -Filter "$ToolName.exe" | % { $_.FullName } 104 | if (@($ToolFilePath).Length -Gt 1) { 105 | Write-Error "There are multiple copies of $ToolName in $($ToolInstallDirectory): `n$(@($ToolFilePath | out-string))" 106 | exit 1 107 | } elseif (@($ToolFilePath).Length -Lt 1) { 108 | Write-Host "$ToolName was not found in $ToolInstallDirectory." 109 | exit 1 110 | } 111 | 112 | # Generate shim 113 | # Always rewrite shims so that we are referencing the expected version 114 | $GenerateShimStatus = CommonLibrary\New-ScriptShim -ShimName $ToolName ` 115 | -ShimDirectory $InstallPath ` 116 | -ToolFilePath "$ToolFilePath" ` 117 | -BaseUri $BaseUri ` 118 | -Force:$Force ` 119 | -Verbose:$Verbose 120 | 121 | if ($GenerateShimStatus -Eq $False) { 122 | Write-PipelineTelemetryError "Generate shim failed" -Category "NativeToolsetBootstrapping" 123 | return 1 124 | } 125 | 126 | exit 0 127 | } 128 | catch { 129 | Write-Host $_.ScriptStackTrace 130 | Write-PipelineTelemetryError -Category "NativeToolsetBootstrapping" -Message $_ 131 | exit 1 132 | } 133 | -------------------------------------------------------------------------------- /eng/common/pipeline-logging-functions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function Write-PipelineTelemetryError { 4 | local telemetry_category='' 5 | local force=false 6 | local function_args=() 7 | local message='' 8 | while [[ $# -gt 0 ]]; do 9 | opt="$(echo "${1/#--/-}" | tr "[:upper:]" "[:lower:]")" 10 | case "$opt" in 11 | -category|-c) 12 | telemetry_category=$2 13 | shift 14 | ;; 15 | -force|-f) 16 | force=true 17 | ;; 18 | -*) 19 | function_args+=("$1 $2") 20 | shift 21 | ;; 22 | *) 23 | message=$* 24 | ;; 25 | esac 26 | shift 27 | done 28 | 29 | if [[ $force != true ]] && [[ "$ci" != true ]]; then 30 | echo "$message" >&2 31 | return 32 | fi 33 | 34 | if [[ $force == true ]]; then 35 | function_args+=("-force") 36 | fi 37 | message="(NETCORE_ENGINEERING_TELEMETRY=$telemetry_category) $message" 38 | function_args+=("$message") 39 | Write-PipelineTaskError ${function_args[@]} 40 | } 41 | 42 | function Write-PipelineTaskError { 43 | local message_type="error" 44 | local sourcepath='' 45 | local linenumber='' 46 | local columnnumber='' 47 | local error_code='' 48 | local force=false 49 | 50 | while [[ $# -gt 0 ]]; do 51 | opt="$(echo "${1/#--/-}" | tr "[:upper:]" "[:lower:]")" 52 | case "$opt" in 53 | -type|-t) 54 | message_type=$2 55 | shift 56 | ;; 57 | -sourcepath|-s) 58 | sourcepath=$2 59 | shift 60 | ;; 61 | -linenumber|-ln) 62 | linenumber=$2 63 | shift 64 | ;; 65 | -columnnumber|-cn) 66 | columnnumber=$2 67 | shift 68 | ;; 69 | -errcode|-e) 70 | error_code=$2 71 | shift 72 | ;; 73 | -force|-f) 74 | force=true 75 | ;; 76 | *) 77 | break 78 | ;; 79 | esac 80 | 81 | shift 82 | done 83 | 84 | if [[ $force != true ]] && [[ "$ci" != true ]]; then 85 | echo "$@" >&2 86 | return 87 | fi 88 | 89 | local message="##vso[task.logissue" 90 | 91 | message="$message type=$message_type" 92 | 93 | if [ -n "$sourcepath" ]; then 94 | message="$message;sourcepath=$sourcepath" 95 | fi 96 | 97 | if [ -n "$linenumber" ]; then 98 | message="$message;linenumber=$linenumber" 99 | fi 100 | 101 | if [ -n "$columnnumber" ]; then 102 | message="$message;columnnumber=$columnnumber" 103 | fi 104 | 105 | if [ -n "$error_code" ]; then 106 | message="$message;code=$error_code" 107 | fi 108 | 109 | message="$message]$*" 110 | echo "$message" 111 | } 112 | 113 | function Write-PipelineSetVariable { 114 | if [[ "$ci" != true ]]; then 115 | return 116 | fi 117 | 118 | local name='' 119 | local value='' 120 | local secret=false 121 | local as_output=false 122 | local is_multi_job_variable=true 123 | 124 | while [[ $# -gt 0 ]]; do 125 | opt="$(echo "${1/#--/-}" | tr "[:upper:]" "[:lower:]")" 126 | case "$opt" in 127 | -name|-n) 128 | name=$2 129 | shift 130 | ;; 131 | -value|-v) 132 | value=$2 133 | shift 134 | ;; 135 | -secret|-s) 136 | secret=true 137 | ;; 138 | -as_output|-a) 139 | as_output=true 140 | ;; 141 | -is_multi_job_variable|-i) 142 | is_multi_job_variable=$2 143 | shift 144 | ;; 145 | esac 146 | shift 147 | done 148 | 149 | value=${value/;/%3B} 150 | value=${value/\\r/%0D} 151 | value=${value/\\n/%0A} 152 | value=${value/]/%5D} 153 | 154 | local message="##vso[task.setvariable variable=$name;isSecret=$secret;isOutput=$is_multi_job_variable]$value" 155 | 156 | if [[ "$as_output" == true ]]; then 157 | $message 158 | else 159 | echo "$message" 160 | fi 161 | } 162 | 163 | function Write-PipelinePrependPath { 164 | local prepend_path='' 165 | 166 | while [[ $# -gt 0 ]]; do 167 | opt="$(echo "${1/#--/-}" | tr "[:upper:]" "[:lower:]")" 168 | case "$opt" in 169 | -path|-p) 170 | prepend_path=$2 171 | shift 172 | ;; 173 | esac 174 | shift 175 | done 176 | 177 | export PATH="$prepend_path:$PATH" 178 | 179 | if [[ "$ci" == true ]]; then 180 | echo "##vso[task.prependpath]$prepend_path" 181 | fi 182 | } 183 | 184 | function Write-PipelineSetResult { 185 | local result='' 186 | local message='' 187 | 188 | while [[ $# -gt 0 ]]; do 189 | opt="$(echo "${1/#--/-}" | tr "[:upper:]" "[:lower:]")" 190 | case "$opt" in 191 | -result|-r) 192 | result=$2 193 | shift 194 | ;; 195 | -message|-m) 196 | message=$2 197 | shift 198 | ;; 199 | esac 200 | shift 201 | done 202 | 203 | if [[ "$ci" == true ]]; then 204 | echo "##vso[task.complete result=$result;]$message" 205 | fi 206 | } 207 | -------------------------------------------------------------------------------- /eng/common/post-build/check-channel-consistency.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory=$true)][string] $PromoteToChannels, # List of channels that the build should be promoted to 3 | [Parameter(Mandatory=$true)][array] $AvailableChannelIds # List of channel IDs available in the YAML implementation 4 | ) 5 | 6 | try { 7 | $ErrorActionPreference = 'Stop' 8 | Set-StrictMode -Version 2.0 9 | 10 | # `tools.ps1` checks $ci to perform some actions. Since the post-build 11 | # scripts don't necessarily execute in the same agent that run the 12 | # build.ps1/sh script this variable isn't automatically set. 13 | $ci = $true 14 | $disableConfigureToolsetImport = $true 15 | . $PSScriptRoot\..\tools.ps1 16 | 17 | if ($PromoteToChannels -eq "") { 18 | Write-PipelineTaskError -Type 'warning' -Message "This build won't publish assets as it's not configured to any Maestro channel. If that wasn't intended use Darc to configure a default channel using add-default-channel for this branch or to promote it to a channel using add-build-to-channel. See https://github.com/dotnet/arcade/blob/main/Documentation/Darc.md#assigning-an-individual-build-to-a-channel for more info." 19 | ExitWithExitCode 0 20 | } 21 | 22 | # Check that every channel that Maestro told to promote the build to 23 | # is available in YAML 24 | $PromoteToChannelsIds = $PromoteToChannels -split "\D" | Where-Object { $_ } 25 | 26 | $hasErrors = $false 27 | 28 | foreach ($id in $PromoteToChannelsIds) { 29 | if (($id -ne 0) -and ($id -notin $AvailableChannelIds)) { 30 | Write-PipelineTaskError -Message "Channel $id is not present in the post-build YAML configuration! This is an error scenario. Please contact @dnceng." 31 | $hasErrors = $true 32 | } 33 | } 34 | 35 | # The `Write-PipelineTaskError` doesn't error the script and we might report several errors 36 | # in the previous lines. The check below makes sure that we return an error state from the 37 | # script if we reported any validation error 38 | if ($hasErrors) { 39 | ExitWithExitCode 1 40 | } 41 | 42 | Write-Host 'done.' 43 | } 44 | catch { 45 | Write-Host $_ 46 | Write-PipelineTelemetryError -Category 'CheckChannelConsistency' -Message "There was an error while trying to check consistency of Maestro default channels for the build and post-build YAML configuration." 47 | ExitWithExitCode 1 48 | } 49 | -------------------------------------------------------------------------------- /eng/common/post-build/nuget-validation.ps1: -------------------------------------------------------------------------------- 1 | # This script validates NuGet package metadata information using this 2 | # tool: https://github.com/NuGet/NuGetGallery/tree/jver-verify/src/VerifyMicrosoftPackage 3 | 4 | param( 5 | [Parameter(Mandatory=$true)][string] $PackagesPath # Path to where the packages to be validated are 6 | ) 7 | 8 | # `tools.ps1` checks $ci to perform some actions. Since the post-build 9 | # scripts don't necessarily execute in the same agent that run the 10 | # build.ps1/sh script this variable isn't automatically set. 11 | $ci = $true 12 | $disableConfigureToolsetImport = $true 13 | . $PSScriptRoot\..\tools.ps1 14 | 15 | try { 16 | & $PSScriptRoot\nuget-verification.ps1 ${PackagesPath}\*.nupkg 17 | } 18 | catch { 19 | Write-Host $_.ScriptStackTrace 20 | Write-PipelineTelemetryError -Category 'NuGetValidation' -Message $_ 21 | ExitWithExitCode 1 22 | } 23 | -------------------------------------------------------------------------------- /eng/common/post-build/nuget-verification.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Verifies that Microsoft NuGet packages have proper metadata. 4 | .DESCRIPTION 5 | Downloads a verification tool and runs metadata validation on the provided NuGet packages. This script writes an 6 | error if any of the provided packages fail validation. All arguments provided to this PowerShell script that do not 7 | match PowerShell parameters are passed on to the verification tool downloaded during the execution of this script. 8 | .PARAMETER NuGetExePath 9 | The path to the nuget.exe binary to use. If not provided, nuget.exe will be downloaded into the -DownloadPath 10 | directory. 11 | .PARAMETER PackageSource 12 | The package source to use to download the verification tool. If not provided, nuget.org will be used. 13 | .PARAMETER DownloadPath 14 | The directory path to download the verification tool and nuget.exe to. If not provided, 15 | %TEMP%\NuGet.VerifyNuGetPackage will be used. 16 | .PARAMETER args 17 | Arguments that will be passed to the verification tool. 18 | .EXAMPLE 19 | PS> .\verify.ps1 *.nupkg 20 | Verifies the metadata of all .nupkg files in the currect working directory. 21 | .EXAMPLE 22 | PS> .\verify.ps1 --help 23 | Displays the help text of the downloaded verifiction tool. 24 | .LINK 25 | https://github.com/NuGet/NuGetGallery/blob/master/src/VerifyMicrosoftPackage/README.md 26 | #> 27 | 28 | # This script was copied from https://github.com/NuGet/NuGetGallery/blob/3e25ad135146676bcab0050a516939d9958bfa5d/src/VerifyMicrosoftPackage/verify.ps1 29 | 30 | [CmdletBinding(PositionalBinding = $false)] 31 | param( 32 | [string]$NuGetExePath, 33 | [string]$PackageSource = "https://api.nuget.org/v3/index.json", 34 | [string]$DownloadPath, 35 | [Parameter(ValueFromRemainingArguments = $true)] 36 | [string[]]$args 37 | ) 38 | 39 | # The URL to download nuget.exe. 40 | $nugetExeUrl = "https://dist.nuget.org/win-x86-commandline/v4.9.4/nuget.exe" 41 | 42 | # The package ID of the verification tool. 43 | $packageId = "NuGet.VerifyMicrosoftPackage" 44 | 45 | # The location that nuget.exe and the verification tool will be downloaded to. 46 | if (!$DownloadPath) { 47 | $DownloadPath = (Join-Path $env:TEMP "NuGet.VerifyMicrosoftPackage") 48 | } 49 | 50 | $fence = New-Object -TypeName string -ArgumentList '=', 80 51 | 52 | # Create the download directory, if it doesn't already exist. 53 | if (!(Test-Path $DownloadPath)) { 54 | New-Item -ItemType Directory $DownloadPath | Out-Null 55 | } 56 | Write-Host "Using download path: $DownloadPath" 57 | 58 | if ($NuGetExePath) { 59 | $nuget = $NuGetExePath 60 | } else { 61 | $downloadedNuGetExe = Join-Path $DownloadPath "nuget.exe" 62 | 63 | # Download nuget.exe, if it doesn't already exist. 64 | if (!(Test-Path $downloadedNuGetExe)) { 65 | Write-Host "Downloading nuget.exe from $nugetExeUrl..." 66 | $ProgressPreference = 'SilentlyContinue' 67 | try { 68 | Invoke-WebRequest $nugetExeUrl -OutFile $downloadedNuGetExe 69 | $ProgressPreference = 'Continue' 70 | } catch { 71 | $ProgressPreference = 'Continue' 72 | Write-Error $_ 73 | Write-Error "nuget.exe failed to download." 74 | exit 75 | } 76 | } 77 | 78 | $nuget = $downloadedNuGetExe 79 | } 80 | 81 | Write-Host "Using nuget.exe path: $nuget" 82 | Write-Host " " 83 | 84 | # Download the latest version of the verification tool. 85 | Write-Host "Downloading the latest version of $packageId from $packageSource..." 86 | Write-Host $fence 87 | & $nuget install $packageId ` 88 | -Prerelease ` 89 | -OutputDirectory $DownloadPath ` 90 | -Source $PackageSource 91 | Write-Host $fence 92 | Write-Host " " 93 | 94 | if ($LASTEXITCODE -ne 0) { 95 | Write-Error "nuget.exe failed to fetch the verify tool." 96 | exit 97 | } 98 | 99 | # Find the most recently downloaded tool 100 | Write-Host "Finding the most recently downloaded verification tool." 101 | $verifyProbePath = Join-Path $DownloadPath "$packageId.*" 102 | $verifyPath = Get-ChildItem -Path $verifyProbePath -Directory ` 103 | | Sort-Object -Property LastWriteTime -Descending ` 104 | | Select-Object -First 1 105 | $verify = Join-Path $verifyPath "tools\NuGet.VerifyMicrosoftPackage.exe" 106 | Write-Host "Using verification tool: $verify" 107 | Write-Host " " 108 | 109 | # Execute the verification tool. 110 | Write-Host "Executing the verify tool..." 111 | Write-Host $fence 112 | & $verify $args 113 | Write-Host $fence 114 | Write-Host " " 115 | 116 | # Respond to the exit code. 117 | if ($LASTEXITCODE -ne 0) { 118 | Write-Error "The verify tool found some problems." 119 | } else { 120 | Write-Output "The verify tool succeeded." 121 | } 122 | -------------------------------------------------------------------------------- /eng/common/post-build/publish-using-darc.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory=$true)][int] $BuildId, 3 | [Parameter(Mandatory=$true)][int] $PublishingInfraVersion, 4 | [Parameter(Mandatory=$true)][string] $AzdoToken, 5 | [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro.dot.net', 6 | [Parameter(Mandatory=$true)][string] $WaitPublishingFinish, 7 | [Parameter(Mandatory=$false)][string] $ArtifactsPublishingAdditionalParameters, 8 | [Parameter(Mandatory=$false)][string] $SymbolPublishingAdditionalParameters 9 | ) 10 | 11 | try { 12 | # `tools.ps1` checks $ci to perform some actions. Since the post-build 13 | # scripts don't necessarily execute in the same agent that run the 14 | # build.ps1/sh script this variable isn't automatically set. 15 | $ci = $true 16 | $disableConfigureToolsetImport = $true 17 | . $PSScriptRoot\..\tools.ps1 18 | 19 | $darc = Get-Darc 20 | 21 | $optionalParams = [System.Collections.ArrayList]::new() 22 | 23 | if ("" -ne $ArtifactsPublishingAdditionalParameters) { 24 | $optionalParams.Add("--artifact-publishing-parameters") | Out-Null 25 | $optionalParams.Add($ArtifactsPublishingAdditionalParameters) | Out-Null 26 | } 27 | 28 | if ("" -ne $SymbolPublishingAdditionalParameters) { 29 | $optionalParams.Add("--symbol-publishing-parameters") | Out-Null 30 | $optionalParams.Add($SymbolPublishingAdditionalParameters) | Out-Null 31 | } 32 | 33 | if ("false" -eq $WaitPublishingFinish) { 34 | $optionalParams.Add("--no-wait") | Out-Null 35 | } 36 | 37 | & $darc add-build-to-channel ` 38 | --id $buildId ` 39 | --publishing-infra-version $PublishingInfraVersion ` 40 | --default-channels ` 41 | --source-branch main ` 42 | --azdev-pat "$AzdoToken" ` 43 | --bar-uri "$MaestroApiEndPoint" ` 44 | --ci ` 45 | --verbose ` 46 | @optionalParams 47 | 48 | if ($LastExitCode -ne 0) { 49 | Write-Host "Problems using Darc to promote build ${buildId} to default channels. Stopping execution..." 50 | exit 1 51 | } 52 | 53 | Write-Host 'done.' 54 | } 55 | catch { 56 | Write-Host $_ 57 | Write-PipelineTelemetryError -Category 'PromoteBuild' -Message "There was an error while trying to publish build '$BuildId' to default channels." 58 | ExitWithExitCode 1 59 | } 60 | -------------------------------------------------------------------------------- /eng/common/post-build/redact-logs.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding(PositionalBinding=$False)] 2 | param( 3 | [Parameter(Mandatory=$true, Position=0)][string] $InputPath, 4 | [Parameter(Mandatory=$true)][string] $BinlogToolVersion, 5 | [Parameter(Mandatory=$false)][string] $DotnetPath, 6 | [Parameter(Mandatory=$false)][string] $PackageFeed = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json', 7 | # File with strings to redact - separated by newlines. 8 | # For comments start the line with '# ' - such lines are ignored 9 | [Parameter(Mandatory=$false)][string] $TokensFilePath, 10 | [Parameter(ValueFromRemainingArguments=$true)][String[]]$TokensToRedact 11 | ) 12 | 13 | try { 14 | $ErrorActionPreference = 'Stop' 15 | Set-StrictMode -Version 2.0 16 | 17 | # `tools.ps1` checks $ci to perform some actions. Since the post-build 18 | # scripts don't necessarily execute in the same agent that run the 19 | # build.ps1/sh script this variable isn't automatically set. 20 | $ci = $true 21 | $disableConfigureToolsetImport = $true 22 | . $PSScriptRoot\..\tools.ps1 23 | 24 | $packageName = 'binlogtool' 25 | 26 | $dotnet = $DotnetPath 27 | 28 | if (!$dotnet) { 29 | $dotnetRoot = InitializeDotNetCli -install:$true 30 | $dotnet = "$dotnetRoot\dotnet.exe" 31 | } 32 | 33 | $toolList = & "$dotnet" tool list -g 34 | 35 | if ($toolList -like "*$packageName*") { 36 | & "$dotnet" tool uninstall $packageName -g 37 | } 38 | 39 | $toolPath = "$PSScriptRoot\..\..\..\.tools" 40 | $verbosity = 'minimal' 41 | 42 | New-Item -ItemType Directory -Force -Path $toolPath 43 | 44 | Push-Location -Path $toolPath 45 | 46 | try { 47 | Write-Host "Installing Binlog redactor CLI..." 48 | Write-Host "'$dotnet' new tool-manifest" 49 | & "$dotnet" new tool-manifest 50 | Write-Host "'$dotnet' tool install $packageName --local --add-source '$PackageFeed' -v $verbosity --version $BinlogToolVersion" 51 | & "$dotnet" tool install $packageName --local --add-source "$PackageFeed" -v $verbosity --version $BinlogToolVersion 52 | 53 | if (Test-Path $TokensFilePath) { 54 | Write-Host "Adding additional sensitive data for redaction from file: " $TokensFilePath 55 | $TokensToRedact += Get-Content -Path $TokensFilePath | Foreach {$_.Trim()} | Where { $_ -notmatch "^# " } 56 | } 57 | 58 | $optionalParams = [System.Collections.ArrayList]::new() 59 | 60 | Foreach ($p in $TokensToRedact) 61 | { 62 | if($p -match '^\$\(.*\)$') 63 | { 64 | Write-Host ("Ignoring token {0} as it is probably unexpanded AzDO variable" -f $p) 65 | } 66 | elseif($p) 67 | { 68 | $optionalParams.Add("-p:" + $p) | Out-Null 69 | } 70 | } 71 | 72 | & $dotnet binlogtool redact --input:$InputPath --recurse --in-place ` 73 | @optionalParams 74 | 75 | if ($LastExitCode -ne 0) { 76 | Write-PipelineTelemetryError -Category 'Redactor' -Type 'warning' -Message "Problems using Redactor tool (exit code: $LastExitCode). But ignoring them now." 77 | } 78 | } 79 | finally { 80 | Pop-Location 81 | } 82 | 83 | Write-Host 'done.' 84 | } 85 | catch { 86 | Write-Host $_ 87 | Write-PipelineTelemetryError -Category 'Redactor' -Message "There was an error while trying to redact logs. Error: $_" 88 | ExitWithExitCode 1 89 | } 90 | -------------------------------------------------------------------------------- /eng/common/retain-build.ps1: -------------------------------------------------------------------------------- 1 | 2 | Param( 3 | [Parameter(Mandatory=$true)][int] $buildId, 4 | [Parameter(Mandatory=$true)][string] $azdoOrgUri, 5 | [Parameter(Mandatory=$true)][string] $azdoProject, 6 | [Parameter(Mandatory=$true)][string] $token 7 | ) 8 | 9 | $ErrorActionPreference = 'Stop' 10 | Set-StrictMode -Version 2.0 11 | 12 | function Get-AzDOHeaders( 13 | [string] $token) 14 | { 15 | $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":${token}")) 16 | $headers = @{"Authorization"="Basic $base64AuthInfo"} 17 | return $headers 18 | } 19 | 20 | function Update-BuildRetention( 21 | [string] $azdoOrgUri, 22 | [string] $azdoProject, 23 | [int] $buildId, 24 | [string] $token) 25 | { 26 | $headers = Get-AzDOHeaders -token $token 27 | $requestBody = "{ 28 | `"keepForever`": `"true`" 29 | }" 30 | 31 | $requestUri = "${azdoOrgUri}/${azdoProject}/_apis/build/builds/${buildId}?api-version=6.0" 32 | write-Host "Attempting to retain build using the following URI: ${requestUri} ..." 33 | 34 | try { 35 | Invoke-RestMethod -Uri $requestUri -Method Patch -Body $requestBody -Header $headers -contentType "application/json" 36 | Write-Host "Updated retention settings for build ${buildId}." 37 | } 38 | catch { 39 | Write-Error "Failed to update retention settings for build: $_.Exception.Response.StatusDescription" 40 | exit 1 41 | } 42 | } 43 | 44 | Update-BuildRetention -azdoOrgUri $azdoOrgUri -azdoProject $azdoProject -buildId $buildId -token $token 45 | exit 0 46 | -------------------------------------------------------------------------------- /eng/common/sdk-task.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding(PositionalBinding=$false)] 2 | Param( 3 | [string] $configuration = 'Debug', 4 | [string] $task, 5 | [string] $verbosity = 'minimal', 6 | [string] $msbuildEngine = $null, 7 | [switch] $restore, 8 | [switch] $prepareMachine, 9 | [switch] $help, 10 | [Parameter(ValueFromRemainingArguments=$true)][String[]]$properties 11 | ) 12 | 13 | $ci = $true 14 | $binaryLog = $true 15 | $warnAsError = $true 16 | 17 | . $PSScriptRoot\tools.ps1 18 | 19 | function Print-Usage() { 20 | Write-Host "Common settings:" 21 | Write-Host " -task Name of Arcade task (name of a project in SdkTasks directory of the Arcade SDK package)" 22 | Write-Host " -restore Restore dependencies" 23 | Write-Host " -verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]" 24 | Write-Host " -help Print help and exit" 25 | Write-Host "" 26 | 27 | Write-Host "Advanced settings:" 28 | Write-Host " -prepareMachine Prepare machine for CI run" 29 | Write-Host " -msbuildEngine Msbuild engine to use to run build ('dotnet', 'vs', or unspecified)." 30 | Write-Host "" 31 | Write-Host "Command line arguments not listed above are passed thru to msbuild." 32 | } 33 | 34 | function Build([string]$target) { 35 | $logSuffix = if ($target -eq 'Execute') { '' } else { ".$target" } 36 | $log = Join-Path $LogDir "$task$logSuffix.binlog" 37 | $outputPath = Join-Path $ToolsetDir "$task\" 38 | 39 | MSBuild $taskProject ` 40 | /bl:$log ` 41 | /t:$target ` 42 | /p:Configuration=$configuration ` 43 | /p:RepoRoot=$RepoRoot ` 44 | /p:BaseIntermediateOutputPath=$outputPath ` 45 | /v:$verbosity ` 46 | @properties 47 | } 48 | 49 | try { 50 | if ($help -or (($null -ne $properties) -and ($properties.Contains('/help') -or $properties.Contains('/?')))) { 51 | Print-Usage 52 | exit 0 53 | } 54 | 55 | if ($task -eq "") { 56 | Write-PipelineTelemetryError -Category 'Build' -Message "Missing required parameter '-task '" 57 | Print-Usage 58 | ExitWithExitCode 1 59 | } 60 | 61 | if( $msbuildEngine -eq "vs") { 62 | # Ensure desktop MSBuild is available for sdk tasks. 63 | if( -not ($GlobalJson.tools.PSObject.Properties.Name -contains "vs" )) { 64 | $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty 65 | } 66 | if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { 67 | $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.10.0-pre.4.0" -MemberType NoteProperty 68 | } 69 | if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { 70 | $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true 71 | } 72 | if ($xcopyMSBuildToolsFolder -eq $null) { 73 | throw 'Unable to get xcopy downloadable version of msbuild' 74 | } 75 | 76 | $global:_MSBuildExe = "$($xcopyMSBuildToolsFolder)\MSBuild\Current\Bin\MSBuild.exe" 77 | } 78 | 79 | $taskProject = GetSdkTaskProject $task 80 | if (!(Test-Path $taskProject)) { 81 | Write-PipelineTelemetryError -Category 'Build' -Message "Unknown task: $task" 82 | ExitWithExitCode 1 83 | } 84 | 85 | if ($restore) { 86 | Build 'Restore' 87 | } 88 | 89 | Build 'Execute' 90 | } 91 | catch { 92 | Write-Host $_.ScriptStackTrace 93 | Write-PipelineTelemetryError -Category 'Build' -Message $_ 94 | ExitWithExitCode 1 95 | } 96 | 97 | ExitWithExitCode 0 98 | -------------------------------------------------------------------------------- /eng/common/sdl/NuGet.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /eng/common/sdl/configure-sdl-tool.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $GuardianCliLocation, 3 | [string] $WorkingDirectory, 4 | [string] $TargetDirectory, 5 | [string] $GdnFolder, 6 | # The list of Guardian tools to configure. For each object in the array: 7 | # - If the item is a [hashtable], it must contain these entries: 8 | # - Name = The tool name as Guardian knows it. 9 | # - Scenario = (Optional) Scenario-specific name for this configuration entry. It must be unique 10 | # among all tool entries with the same Name. 11 | # - Args = (Optional) Array of Guardian tool configuration args, like '@("Target > C:\temp")' 12 | # - If the item is a [string] $v, it is treated as '@{ Name="$v" }' 13 | [object[]] $ToolsList, 14 | [string] $GuardianLoggerLevel='Standard', 15 | # Optional: Additional params to add to any tool using CredScan. 16 | [string[]] $CrScanAdditionalRunConfigParams, 17 | # Optional: Additional params to add to any tool using PoliCheck. 18 | [string[]] $PoliCheckAdditionalRunConfigParams, 19 | # Optional: Additional params to add to any tool using CodeQL/Semmle. 20 | [string[]] $CodeQLAdditionalRunConfigParams, 21 | # Optional: Additional params to add to any tool using Binskim. 22 | [string[]] $BinskimAdditionalRunConfigParams 23 | ) 24 | 25 | $ErrorActionPreference = 'Stop' 26 | Set-StrictMode -Version 2.0 27 | $disableConfigureToolsetImport = $true 28 | $global:LASTEXITCODE = 0 29 | 30 | try { 31 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 32 | # scripts don't necessarily execute in the same agent that run the 33 | # build.ps1/sh script this variable isn't automatically set. 34 | $ci = $true 35 | . $PSScriptRoot\..\tools.ps1 36 | 37 | # Normalize tools list: all in [hashtable] form with defined values for each key. 38 | $ToolsList = $ToolsList | 39 | ForEach-Object { 40 | if ($_ -is [string]) { 41 | $_ = @{ Name = $_ } 42 | } 43 | 44 | if (-not ($_['Scenario'])) { $_.Scenario = "" } 45 | if (-not ($_['Args'])) { $_.Args = @() } 46 | $_ 47 | } 48 | 49 | Write-Host "List of tools to configure:" 50 | $ToolsList | ForEach-Object { $_ | Out-String | Write-Host } 51 | 52 | # We store config files in the r directory of .gdn 53 | $gdnConfigPath = Join-Path $GdnFolder 'r' 54 | $ValidPath = Test-Path $GuardianCliLocation 55 | 56 | if ($ValidPath -eq $False) 57 | { 58 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Invalid Guardian CLI Location." 59 | ExitWithExitCode 1 60 | } 61 | 62 | foreach ($tool in $ToolsList) { 63 | # Put together the name and scenario to make a unique key. 64 | $toolConfigName = $tool.Name 65 | if ($tool.Scenario) { 66 | $toolConfigName += "_" + $tool.Scenario 67 | } 68 | 69 | Write-Host "=== Configuring $toolConfigName..." 70 | 71 | $gdnConfigFile = Join-Path $gdnConfigPath "$toolConfigName-configure.gdnconfig" 72 | 73 | # For some tools, add default and automatic args. 74 | switch -Exact ($tool.Name) { 75 | 'credscan' { 76 | if ($targetDirectory) { 77 | $tool.Args += "`"TargetDirectory < $TargetDirectory`"" 78 | } 79 | $tool.Args += "`"OutputType < pre`"" 80 | $tool.Args += $CrScanAdditionalRunConfigParams 81 | } 82 | 'policheck' { 83 | if ($targetDirectory) { 84 | $tool.Args += "`"Target < $TargetDirectory`"" 85 | } 86 | $tool.Args += $PoliCheckAdditionalRunConfigParams 87 | } 88 | {$_ -in 'semmle', 'codeql'} { 89 | if ($targetDirectory) { 90 | $tool.Args += "`"SourceCodeDirectory < $TargetDirectory`"" 91 | } 92 | $tool.Args += $CodeQLAdditionalRunConfigParams 93 | } 94 | 'binskim' { 95 | if ($targetDirectory) { 96 | # Binskim crashes due to specific PDBs. GitHub issue: https://github.com/microsoft/binskim/issues/924. 97 | # We are excluding all `_.pdb` files from the scan. 98 | $tool.Args += "`"Target < $TargetDirectory\**;-:file|$TargetDirectory\**\_.pdb`"" 99 | } 100 | $tool.Args += $BinskimAdditionalRunConfigParams 101 | } 102 | } 103 | 104 | # Create variable pointing to the args array directly so we can use splat syntax later. 105 | $toolArgs = $tool.Args 106 | 107 | # Configure the tool. If args array is provided or the current tool has some default arguments 108 | # defined, add "--args" and splat each element on the end. Arg format is "{Arg id} < {Value}", 109 | # one per parameter. Doc page for "guardian configure": 110 | # https://dev.azure.com/securitytools/SecurityIntegration/_wiki/wikis/Guardian/1395/configure 111 | Exec-BlockVerbosely { 112 | & $GuardianCliLocation configure ` 113 | --working-directory $WorkingDirectory ` 114 | --tool $tool.Name ` 115 | --output-path $gdnConfigFile ` 116 | --logger-level $GuardianLoggerLevel ` 117 | --noninteractive ` 118 | --force ` 119 | $(if ($toolArgs) { "--args" }) @toolArgs 120 | Exit-IfNZEC "Sdl" 121 | } 122 | 123 | Write-Host "Created '$toolConfigName' configuration file: $gdnConfigFile" 124 | } 125 | } 126 | catch { 127 | Write-Host $_.ScriptStackTrace 128 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 129 | ExitWithExitCode 1 130 | } 131 | -------------------------------------------------------------------------------- /eng/common/sdl/extract-artifact-archives.ps1: -------------------------------------------------------------------------------- 1 | # This script looks for each archive file in a directory and extracts it into the target directory. 2 | # For example, the file "$InputPath/bin.tar.gz" extracts to "$ExtractPath/bin.tar.gz.extracted/**". 3 | # Uses the "tar" utility added to Windows 10 / Windows 2019 that supports tar.gz and zip. 4 | param( 5 | # Full path to directory where archives are stored. 6 | [Parameter(Mandatory=$true)][string] $InputPath, 7 | # Full path to directory to extract archives into. May be the same as $InputPath. 8 | [Parameter(Mandatory=$true)][string] $ExtractPath 9 | ) 10 | 11 | $ErrorActionPreference = 'Stop' 12 | Set-StrictMode -Version 2.0 13 | 14 | $disableConfigureToolsetImport = $true 15 | 16 | try { 17 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 18 | # scripts don't necessarily execute in the same agent that run the 19 | # build.ps1/sh script this variable isn't automatically set. 20 | $ci = $true 21 | . $PSScriptRoot\..\tools.ps1 22 | 23 | Measure-Command { 24 | $jobs = @() 25 | 26 | # Find archive files for non-Windows and Windows builds. 27 | $archiveFiles = @( 28 | Get-ChildItem (Join-Path $InputPath "*.tar.gz") 29 | Get-ChildItem (Join-Path $InputPath "*.zip") 30 | ) 31 | 32 | foreach ($targzFile in $archiveFiles) { 33 | $jobs += Start-Job -ScriptBlock { 34 | $file = $using:targzFile 35 | $fileName = [System.IO.Path]::GetFileName($file) 36 | $extractDir = Join-Path $using:ExtractPath "$fileName.extracted" 37 | 38 | New-Item $extractDir -ItemType Directory -Force | Out-Null 39 | 40 | Write-Host "Extracting '$file' to '$extractDir'..." 41 | 42 | # Pipe errors to stdout to prevent PowerShell detecting them and quitting the job early. 43 | # This type of quit skips the catch, so we wouldn't be able to tell which file triggered the 44 | # error. Save output so it can be stored in the exception string along with context. 45 | $output = tar -xf $file -C $extractDir 2>&1 46 | # Handle NZEC manually rather than using Exit-IfNZEC: we are in a background job, so we 47 | # don't have access to the outer scope. 48 | if ($LASTEXITCODE -ne 0) { 49 | throw "Error extracting '$file': non-zero exit code ($LASTEXITCODE). Output: '$output'" 50 | } 51 | 52 | Write-Host "Extracted to $extractDir" 53 | } 54 | } 55 | 56 | Receive-Job $jobs -Wait 57 | } 58 | } 59 | catch { 60 | Write-Host $_ 61 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 62 | ExitWithExitCode 1 63 | } 64 | -------------------------------------------------------------------------------- /eng/common/sdl/extract-artifact-packages.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where artifact packages are stored 3 | [Parameter(Mandatory=$true)][string] $ExtractPath # Full path to directory where the packages will be extracted 4 | ) 5 | 6 | $ErrorActionPreference = 'Stop' 7 | Set-StrictMode -Version 2.0 8 | 9 | $disableConfigureToolsetImport = $true 10 | 11 | function ExtractArtifacts { 12 | if (!(Test-Path $InputPath)) { 13 | Write-Host "Input Path does not exist: $InputPath" 14 | ExitWithExitCode 0 15 | } 16 | $Jobs = @() 17 | Get-ChildItem "$InputPath\*.nupkg" | 18 | ForEach-Object { 19 | $Jobs += Start-Job -ScriptBlock $ExtractPackage -ArgumentList $_.FullName 20 | } 21 | 22 | foreach ($Job in $Jobs) { 23 | Wait-Job -Id $Job.Id | Receive-Job 24 | } 25 | } 26 | 27 | try { 28 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 29 | # scripts don't necessarily execute in the same agent that run the 30 | # build.ps1/sh script this variable isn't automatically set. 31 | $ci = $true 32 | . $PSScriptRoot\..\tools.ps1 33 | 34 | $ExtractPackage = { 35 | param( 36 | [string] $PackagePath # Full path to a NuGet package 37 | ) 38 | 39 | if (!(Test-Path $PackagePath)) { 40 | Write-PipelineTelemetryError -Category 'Build' -Message "Input file does not exist: $PackagePath" 41 | ExitWithExitCode 1 42 | } 43 | 44 | $RelevantExtensions = @('.dll', '.exe', '.pdb') 45 | Write-Host -NoNewLine 'Extracting ' ([System.IO.Path]::GetFileName($PackagePath)) '...' 46 | 47 | $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) 48 | $ExtractPath = Join-Path -Path $using:ExtractPath -ChildPath $PackageId 49 | 50 | Add-Type -AssemblyName System.IO.Compression.FileSystem 51 | 52 | [System.IO.Directory]::CreateDirectory($ExtractPath); 53 | 54 | try { 55 | $zip = [System.IO.Compression.ZipFile]::OpenRead($PackagePath) 56 | 57 | $zip.Entries | 58 | Where-Object {$RelevantExtensions -contains [System.IO.Path]::GetExtension($_.Name)} | 59 | ForEach-Object { 60 | $TargetPath = Join-Path -Path $ExtractPath -ChildPath (Split-Path -Path $_.FullName) 61 | [System.IO.Directory]::CreateDirectory($TargetPath); 62 | 63 | $TargetFile = Join-Path -Path $ExtractPath -ChildPath $_.FullName 64 | [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $TargetFile) 65 | } 66 | } 67 | catch { 68 | Write-Host $_ 69 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 70 | ExitWithExitCode 1 71 | } 72 | finally { 73 | $zip.Dispose() 74 | } 75 | } 76 | Measure-Command { ExtractArtifacts } 77 | } 78 | catch { 79 | Write-Host $_ 80 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 81 | ExitWithExitCode 1 82 | } 83 | -------------------------------------------------------------------------------- /eng/common/sdl/init-sdl.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $GuardianCliLocation, 3 | [string] $Repository, 4 | [string] $BranchName='master', 5 | [string] $WorkingDirectory, 6 | [string] $AzureDevOpsAccessToken, 7 | [string] $GuardianLoggerLevel='Standard' 8 | ) 9 | 10 | $ErrorActionPreference = 'Stop' 11 | Set-StrictMode -Version 2.0 12 | $disableConfigureToolsetImport = $true 13 | $global:LASTEXITCODE = 0 14 | 15 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 16 | # scripts don't necessarily execute in the same agent that run the 17 | # build.ps1/sh script this variable isn't automatically set. 18 | $ci = $true 19 | . $PSScriptRoot\..\tools.ps1 20 | 21 | # Don't display the console progress UI - it's a huge perf hit 22 | $ProgressPreference = 'SilentlyContinue' 23 | 24 | # Construct basic auth from AzDO access token; construct URI to the repository's gdn folder stored in that repository; construct location of zip file 25 | $encodedPat = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$AzureDevOpsAccessToken")) 26 | $escapedRepository = [Uri]::EscapeDataString("/$Repository/$BranchName/.gdn") 27 | $uri = "https://dev.azure.com/dnceng/internal/_apis/git/repositories/sdl-tool-cfg/Items?path=$escapedRepository&versionDescriptor[versionOptions]=0&`$format=zip&api-version=5.0" 28 | $zipFile = "$WorkingDirectory/gdn.zip" 29 | 30 | Add-Type -AssemblyName System.IO.Compression.FileSystem 31 | $gdnFolder = (Join-Path $WorkingDirectory '.gdn') 32 | 33 | try { 34 | # if the folder does not exist, we'll do a guardian init and push it to the remote repository 35 | Write-Host 'Initializing Guardian...' 36 | Write-Host "$GuardianCliLocation init --working-directory $WorkingDirectory --logger-level $GuardianLoggerLevel" 37 | & $GuardianCliLocation init --working-directory $WorkingDirectory --logger-level $GuardianLoggerLevel 38 | if ($LASTEXITCODE -ne 0) { 39 | Write-PipelineTelemetryError -Force -Category 'Build' -Message "Guardian init failed with exit code $LASTEXITCODE." 40 | ExitWithExitCode $LASTEXITCODE 41 | } 42 | # We create the mainbaseline so it can be edited later 43 | Write-Host "$GuardianCliLocation baseline --working-directory $WorkingDirectory --name mainbaseline" 44 | & $GuardianCliLocation baseline --working-directory $WorkingDirectory --name mainbaseline 45 | if ($LASTEXITCODE -ne 0) { 46 | Write-PipelineTelemetryError -Force -Category 'Build' -Message "Guardian baseline failed with exit code $LASTEXITCODE." 47 | ExitWithExitCode $LASTEXITCODE 48 | } 49 | ExitWithExitCode 0 50 | } 51 | catch { 52 | Write-Host $_.ScriptStackTrace 53 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 54 | ExitWithExitCode 1 55 | } 56 | -------------------------------------------------------------------------------- /eng/common/sdl/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /eng/common/sdl/run-sdl.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $GuardianCliLocation, 3 | [string] $WorkingDirectory, 4 | [string] $GdnFolder, 5 | [string] $UpdateBaseline, 6 | [string] $GuardianLoggerLevel='Standard' 7 | ) 8 | 9 | $ErrorActionPreference = 'Stop' 10 | Set-StrictMode -Version 2.0 11 | $disableConfigureToolsetImport = $true 12 | $global:LASTEXITCODE = 0 13 | 14 | try { 15 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 16 | # scripts don't necessarily execute in the same agent that run the 17 | # build.ps1/sh script this variable isn't automatically set. 18 | $ci = $true 19 | . $PSScriptRoot\..\tools.ps1 20 | 21 | # We store config files in the r directory of .gdn 22 | $gdnConfigPath = Join-Path $GdnFolder 'r' 23 | $ValidPath = Test-Path $GuardianCliLocation 24 | 25 | if ($ValidPath -eq $False) 26 | { 27 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Invalid Guardian CLI Location." 28 | ExitWithExitCode 1 29 | } 30 | 31 | $gdnConfigFiles = Get-ChildItem $gdnConfigPath -Recurse -Include '*.gdnconfig' 32 | Write-Host "Discovered Guardian config files:" 33 | $gdnConfigFiles | Out-String | Write-Host 34 | 35 | Exec-BlockVerbosely { 36 | & $GuardianCliLocation run ` 37 | --working-directory $WorkingDirectory ` 38 | --baseline mainbaseline ` 39 | --update-baseline $UpdateBaseline ` 40 | --logger-level $GuardianLoggerLevel ` 41 | --config @gdnConfigFiles 42 | Exit-IfNZEC "Sdl" 43 | } 44 | } 45 | catch { 46 | Write-Host $_.ScriptStackTrace 47 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 48 | ExitWithExitCode 1 49 | } 50 | -------------------------------------------------------------------------------- /eng/common/sdl/sdl.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Install-Gdn { 3 | param( 4 | [Parameter(Mandatory=$true)] 5 | [string]$Path, 6 | 7 | # If omitted, install the latest version of Guardian, otherwise install that specific version. 8 | [string]$Version 9 | ) 10 | 11 | $ErrorActionPreference = 'Stop' 12 | Set-StrictMode -Version 2.0 13 | $disableConfigureToolsetImport = $true 14 | $global:LASTEXITCODE = 0 15 | 16 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 17 | # scripts don't necessarily execute in the same agent that run the 18 | # build.ps1/sh script this variable isn't automatically set. 19 | $ci = $true 20 | . $PSScriptRoot\..\tools.ps1 21 | 22 | $argumentList = @("install", "Microsoft.Guardian.Cli", "-Source https://securitytools.pkgs.visualstudio.com/_packaging/Guardian/nuget/v3/index.json", "-OutputDirectory $Path", "-NonInteractive", "-NoCache") 23 | 24 | if ($Version) { 25 | $argumentList += "-Version $Version" 26 | } 27 | 28 | Start-Process nuget -Verbose -ArgumentList $argumentList -NoNewWindow -Wait 29 | 30 | $gdnCliPath = Get-ChildItem -Filter guardian.cmd -Recurse -Path $Path 31 | 32 | if (!$gdnCliPath) 33 | { 34 | Write-PipelineTelemetryError -Category 'Sdl' -Message 'Failure installing Guardian' 35 | } 36 | 37 | return $gdnCliPath.FullName 38 | } -------------------------------------------------------------------------------- /eng/common/sdl/trim-assets-version.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Install and run the 'Microsoft.DotNet.VersionTools.Cli' tool with the 'trim-artifacts-version' command to trim the version from the NuGet assets file name. 4 | 5 | .PARAMETER InputPath 6 | Full path to directory where artifact packages are stored 7 | 8 | .PARAMETER Recursive 9 | Search for NuGet packages recursively 10 | 11 | #> 12 | 13 | Param( 14 | [string] $InputPath, 15 | [bool] $Recursive = $true 16 | ) 17 | 18 | $CliToolName = "Microsoft.DotNet.VersionTools.Cli" 19 | 20 | function Install-VersionTools-Cli { 21 | param( 22 | [Parameter(Mandatory=$true)][string]$Version 23 | ) 24 | 25 | Write-Host "Installing the package '$CliToolName' with a version of '$version' ..." 26 | $feed = "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" 27 | 28 | $argumentList = @("tool", "install", "--local", "$CliToolName", "--add-source $feed", "--no-cache", "--version $Version", "--create-manifest-if-needed") 29 | Start-Process "$dotnet" -Verbose -ArgumentList $argumentList -NoNewWindow -Wait 30 | } 31 | 32 | # ------------------------------------------------------------------- 33 | 34 | if (!(Test-Path $InputPath)) { 35 | Write-Host "Input Path '$InputPath' does not exist" 36 | ExitWithExitCode 1 37 | } 38 | 39 | $ErrorActionPreference = 'Stop' 40 | Set-StrictMode -Version 2.0 41 | 42 | $disableConfigureToolsetImport = $true 43 | $global:LASTEXITCODE = 0 44 | 45 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 46 | # scripts don't necessarily execute in the same agent that run the 47 | # build.ps1/sh script this variable isn't automatically set. 48 | $ci = $true 49 | . $PSScriptRoot\..\tools.ps1 50 | 51 | try { 52 | $dotnetRoot = InitializeDotNetCli -install:$true 53 | $dotnet = "$dotnetRoot\dotnet.exe" 54 | 55 | $toolsetVersion = Read-ArcadeSdkVersion 56 | Install-VersionTools-Cli -Version $toolsetVersion 57 | 58 | $cliToolFound = (& "$dotnet" tool list --local | Where-Object {$_.Split(' ')[0] -eq $CliToolName}) 59 | if ($null -eq $cliToolFound) { 60 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "The '$CliToolName' tool is not installed." 61 | ExitWithExitCode 1 62 | } 63 | 64 | Exec-BlockVerbosely { 65 | & "$dotnet" $CliToolName trim-assets-version ` 66 | --assets-path $InputPath ` 67 | --recursive $Recursive 68 | Exit-IfNZEC "Sdl" 69 | } 70 | } 71 | catch { 72 | Write-Host $_ 73 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 74 | ExitWithExitCode 1 75 | } 76 | -------------------------------------------------------------------------------- /eng/key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet-contrib/AspNet.Security.OpenId.Providers/14f7589c93e6a3c5210e9d414651390808eb36eb/eng/key.snk -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "9.0.301", 4 | "allowPrerelease": true, 5 | "rollForward": "major" 6 | }, 7 | 8 | "tools": { 9 | "dotnet": "9.0.301" 10 | }, 11 | 12 | "msbuild-sdks": { 13 | "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24453.1", 14 | "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24453.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /package-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet-contrib/AspNet.Security.OpenId.Providers/14f7589c93e6a3c5210e9d414651390808eb36eb/package-icon.png -------------------------------------------------------------------------------- /samples/Mvc.Client/Controllers/AuthenticationController.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using Microsoft.AspNetCore.Authentication.Cookies; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Mvc.Client.Extensions; 10 | 11 | namespace Mvc.Client.Controllers; 12 | 13 | public class AuthenticationController : Controller 14 | { 15 | [HttpGet("~/signin")] 16 | public async Task SignIn() => View("SignIn", await HttpContext.GetExternalProvidersAsync()); 17 | 18 | [HttpPost("~/signin")] 19 | public async Task SignIn([FromForm] string provider) 20 | { 21 | // Note: the "provider" parameter corresponds to the external 22 | // authentication provider choosen by the user agent. 23 | if (string.IsNullOrWhiteSpace(provider)) 24 | { 25 | return BadRequest(); 26 | } 27 | 28 | if (!await HttpContext.IsProviderSupportedAsync(provider)) 29 | { 30 | return BadRequest(); 31 | } 32 | 33 | // Instruct the middleware corresponding to the requested external identity 34 | // provider to redirect the user agent to its own authorization endpoint. 35 | // Note: the authenticationScheme parameter must match the value configured in Startup.cs 36 | return Challenge(new AuthenticationProperties { RedirectUri = "/" }, provider); 37 | } 38 | 39 | [HttpGet("~/signout"), HttpPost("~/signout")] 40 | public IActionResult SignOutCurrentUser() 41 | { 42 | // Instruct the cookies middleware to delete the local cookie created 43 | // when the user agent is redirected from the external identity provider 44 | // after a successful authentication flow (e.g Google or Facebook). 45 | return SignOut(new AuthenticationProperties { RedirectUri = "/" }, 46 | CookieAuthenticationDefaults.AuthenticationScheme); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /samples/Mvc.Client/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using Microsoft.AspNetCore.Mvc; 8 | 9 | namespace Mvc.Client.Controllers; 10 | 11 | public class HomeController : Controller 12 | { 13 | [HttpGet("~/")] 14 | public ActionResult Index() => View(); 15 | } 16 | -------------------------------------------------------------------------------- /samples/Mvc.Client/Extensions/HttpContextExtensions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | namespace Mvc.Client.Extensions; 8 | 9 | public static class HttpContextExtensions 10 | { 11 | public static async Task GetExternalProvidersAsync(this HttpContext context) 12 | { 13 | ArgumentNullException.ThrowIfNull(context); 14 | 15 | var schemes = context.RequestServices.GetRequiredService(); 16 | 17 | return (from scheme in await schemes.GetAllSchemesAsync() 18 | where !string.IsNullOrEmpty(scheme.DisplayName) 19 | select scheme).ToArray(); 20 | } 21 | 22 | public static async Task IsProviderSupportedAsync(this HttpContext context, string provider) 23 | { 24 | ArgumentNullException.ThrowIfNull(context); 25 | 26 | return (from scheme in await context.GetExternalProvidersAsync() 27 | where string.Equals(scheme.Name, provider, StringComparison.OrdinalIgnoreCase) 28 | select scheme).Any(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /samples/Mvc.Client/Mvc.Client.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | false 5 | $(DefaultNetCoreTargetFramework) 6 | AspNet.Security.OpenId.Providers.Mvc.Client 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /samples/Mvc.Client/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Mvc.Client; 2 | 3 | public static class Program 4 | { 5 | public static void Main(string[] args) 6 | => CreateHostBuilder(args).Build().Run(); 7 | 8 | public static IHostBuilder CreateHostBuilder(string[] args) => 9 | Host.CreateDefaultBuilder(args) 10 | .ConfigureWebHostDefaults( 11 | (webBuilder) => webBuilder.UseStartup()); 12 | } 13 | -------------------------------------------------------------------------------- /samples/Mvc.Client/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54879/", 7 | "sslPort": 44316 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "web": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "launchUrl": "https://localhost:44316/", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/Mvc.Client/Startup.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using Microsoft.AspNetCore.Authentication.Cookies; 8 | 9 | namespace Mvc.Client; 10 | 11 | public class Startup 12 | { 13 | public void ConfigureServices(IServiceCollection services) 14 | { 15 | services.AddAuthentication(options => 16 | { 17 | options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; 18 | }) 19 | 20 | .AddCookie(options => 21 | { 22 | options.LoginPath = "/login"; 23 | options.LogoutPath = "/signout"; 24 | }) 25 | 26 | .AddOpenId("StackExchange", "StackExchange", options => 27 | { 28 | options.Authority = new Uri("https://openid.stackexchange.com/"); 29 | options.CallbackPath = "/signin-stackexchange"; 30 | }) 31 | 32 | .AddSteam(); 33 | 34 | services.AddControllersWithViews(); 35 | } 36 | 37 | public void Configure(IApplicationBuilder app) 38 | { 39 | app.UseStaticFiles(); 40 | 41 | app.UseRouting(); 42 | 43 | app.UseAuthentication(); 44 | app.UseAuthorization(); 45 | 46 | app.UseEndpoints(endpoints => 47 | { 48 | endpoints.MapDefaultControllerRoute(); 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /samples/Mvc.Client/Views/Authentication/SignIn.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Authentication 2 | @model AuthenticationScheme[] 3 | 4 |
5 |

Authentication

6 |

Sign in using one of these external providers:

7 | 8 | @foreach (var scheme in Model!.OrderBy(p => p.DisplayName)) 9 | { 10 |
11 | 12 | 13 | 14 | 15 |
16 | } 17 |
18 | -------------------------------------------------------------------------------- /samples/Mvc.Client/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 
2 | @if (User?.Identity?.IsAuthenticated ?? false) 3 | { 4 |

Welcome, @User.Identity.Name

5 | 6 |

7 | @foreach (var claim in Context.User.Claims) 8 | { 9 |

@claim.Type: @claim.Value
10 | } 11 |

12 | 13 | Sign out 14 | } 15 | 16 | else 17 | { 18 |

Welcome, anonymous

19 | Sign in 20 | } 21 |
-------------------------------------------------------------------------------- /samples/Mvc.Client/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Mvc.Client (OpenID 2.0 sample) 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |

Your application (Mvc.Client)

22 |
23 | 24 | @RenderBody() 25 | 26 |
27 |

© Your company @DateTime.UtcNow.Year

28 |
29 | 30 |
31 | 32 | -------------------------------------------------------------------------------- /samples/Mvc.Client/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId.Steam/AspNet.Security.OpenId.Steam.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(DefaultNetCoreTargetFramework) 5 | 6 | 7 | 8 | ASP.NET Core authentication middleware for Steam. 9 | Kévin Chalet 10 | aspnetcore;authentication;openid;security;steam 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId.Steam/SteamAuthenticationConstants.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | namespace AspNet.Security.OpenId.Steam; 8 | 9 | public static class SteamAuthenticationConstants 10 | { 11 | public static class Namespaces 12 | { 13 | public const string Identifier = "https://steamcommunity.com/openid/id/"; 14 | public const string LegacyIdentifier = "http://steamcommunity.com/openid/id/"; 15 | } 16 | 17 | public static class Parameters 18 | { 19 | public const string Key = "key"; 20 | public const string SteamId = "steamids"; 21 | public const string Response = "response"; 22 | public const string Players = "players"; 23 | public const string Name = "personaname"; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId.Steam/SteamAuthenticationDefaults.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | namespace AspNet.Security.OpenId.Steam; 8 | 9 | /// 10 | /// Contains various constants used as default values 11 | /// for the Steam authentication middleware. 12 | /// 13 | public static class SteamAuthenticationDefaults 14 | { 15 | /// 16 | /// Gets the default value associated with . 17 | /// 18 | public const string AuthenticationScheme = "Steam"; 19 | 20 | /// 21 | /// Gets the default value associated with . 22 | /// 23 | public static readonly string DisplayName = "Steam"; 24 | 25 | /// 26 | /// Gets the default value associated with . 27 | /// 28 | public static readonly string CallbackPath = "/signin-steam"; 29 | 30 | /// 31 | /// Gets the default value associated with . 32 | /// 33 | public static readonly string Authority = "https://steamcommunity.com/openid/"; 34 | 35 | /// 36 | /// Gets the default value associated with . 37 | /// 38 | public static readonly string UserInformationEndpoint = "https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/"; 39 | } 40 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId.Steam/SteamAuthenticationExtensions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using AspNet.Security.OpenId.Steam; 8 | 9 | namespace Microsoft.Extensions.DependencyInjection; 10 | 11 | /// 12 | /// Exposes convenient extensions that can be used to add an instance 13 | /// of the Steam authentication middleware in an ASP.NET Core pipeline. 14 | /// 15 | public static class SteamAuthenticationExtensions 16 | { 17 | /// 18 | /// Adds to the specified 19 | /// , which enables Steam authentication capabilities. 20 | /// 21 | /// The authentication builder. 22 | /// The . 23 | public static AuthenticationBuilder AddSteam([NotNull] this AuthenticationBuilder builder) 24 | { 25 | return builder.AddSteam(SteamAuthenticationDefaults.AuthenticationScheme, options => { }); 26 | } 27 | 28 | /// 29 | /// Adds to the specified 30 | /// , which enables Steam authentication capabilities. 31 | /// 32 | /// The authentication builder. 33 | /// The delegate used to configure the OpenID 2.0 options. 34 | /// The . 35 | public static AuthenticationBuilder AddSteam( 36 | [NotNull] this AuthenticationBuilder builder, 37 | [NotNull] Action configuration) 38 | { 39 | return builder.AddSteam(SteamAuthenticationDefaults.AuthenticationScheme, configuration); 40 | } 41 | 42 | /// 43 | /// Adds to the specified 44 | /// , which enables Steam authentication capabilities. 45 | /// 46 | /// The authentication builder. 47 | /// The authentication scheme associated with this instance. 48 | /// The delegate used to configure the Steam options. 49 | /// The . 50 | public static AuthenticationBuilder AddSteam( 51 | [NotNull] this AuthenticationBuilder builder, [NotNull] string scheme, 52 | [NotNull] Action configuration) 53 | { 54 | return builder.AddSteam(scheme, SteamAuthenticationDefaults.DisplayName, configuration); 55 | } 56 | 57 | /// 58 | /// Adds to the specified 59 | /// , which enables Steam authentication capabilities. 60 | /// 61 | /// The authentication builder. 62 | /// The authentication scheme associated with this instance. 63 | /// The optional display name associated with this instance. 64 | /// The delegate used to configure the Steam options. 65 | /// The . 66 | public static AuthenticationBuilder AddSteam( 67 | [NotNull] this AuthenticationBuilder builder, 68 | [NotNull] string scheme, [CanBeNull] string caption, 69 | [NotNull] Action configuration) 70 | { 71 | return builder.AddOpenId(scheme, caption, configuration); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId.Steam/SteamAuthenticationOptions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | namespace AspNet.Security.OpenId.Steam; 8 | 9 | public class SteamAuthenticationOptions : OpenIdAuthenticationOptions 10 | { 11 | public SteamAuthenticationOptions() 12 | { 13 | Authority = new Uri(SteamAuthenticationDefaults.Authority); 14 | CallbackPath = SteamAuthenticationDefaults.CallbackPath; 15 | } 16 | 17 | /// 18 | /// Gets or sets the application key used to retrieve user details from Steam's API. 19 | /// 20 | public string? ApplicationKey { get; set; } 21 | 22 | /// 23 | /// Gets or sets the endpoint used to retrieve user details. 24 | /// 25 | public string UserInformationEndpoint { get; set; } = SteamAuthenticationDefaults.UserInformationEndpoint; 26 | } 27 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId/AspNet.Security.OpenId.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(DefaultNetCoreTargetFramework) 5 | 6 | 7 | 8 | ASP.NET Core authentication middleware for OpenID 2.0 providers. 9 | Kévin Chalet 10 | aspnetcore;authentication;openid;security 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId/Events/OpenIdAuthenticatedContext.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using System.Security.Claims; 8 | using System.Text.Json; 9 | using Microsoft.AspNetCore.Http; 10 | 11 | namespace AspNet.Security.OpenId; 12 | 13 | /// 14 | /// Exposes various information about the current OpenID authentication flow. 15 | /// 16 | public class OpenIdAuthenticatedContext( 17 | [NotNull] HttpContext context, 18 | [NotNull] AuthenticationScheme scheme, 19 | [NotNull] OpenIdAuthenticationOptions options, 20 | [NotNull] AuthenticationTicket ticket) : BaseContext(context, scheme, options) 21 | { 22 | /// 23 | /// Gets or sets the authentication ticket. 24 | /// 25 | public AuthenticationTicket Ticket { get; set; } = ticket; 26 | 27 | /// 28 | /// Gets the identity containing the claims associated with the current user. 29 | /// 30 | public ClaimsIdentity? Identity => Ticket?.Principal?.Identity as ClaimsIdentity; 31 | 32 | /// 33 | /// Gets the identifier returned by the identity provider. 34 | /// 35 | public string? Identifier => Ticket?.Principal?.FindFirst(ClaimTypes.NameIdentifier)?.Value; 36 | 37 | /// 38 | /// Gets the authentication properties associated with the ticket. 39 | /// 40 | public AuthenticationProperties? Properties => Ticket?.Properties; 41 | 42 | /// 43 | /// Gets or sets the attributes associated with the current user. 44 | /// 45 | public IDictionary Attributes { get; } = new Dictionary(); 46 | 47 | /// 48 | /// Gets or sets the optional JSON payload extracted from the current request. 49 | /// This property is not set by the generic middleware but can be used by specialized middleware. 50 | /// 51 | public JsonDocument? UserPayload { get; set; } 52 | } 53 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId/Events/OpenIdRedirectContext.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using Microsoft.AspNetCore.Http; 8 | 9 | namespace AspNet.Security.OpenId.Events; 10 | 11 | public class OpenIdRedirectContext(HttpContext context, 12 | AuthenticationScheme scheme, 13 | OpenIdAuthenticationOptions options, 14 | AuthenticationProperties properties, 15 | OpenIdAuthenticationMessage message) : PropertiesContext(context, scheme, options, properties) 16 | { 17 | /// 18 | /// Gets or sets the protocol message that has been generated by the handler up to this point. 19 | /// 20 | public OpenIdAuthenticationMessage ProtocolMessage { get; set; } = message; 21 | } 22 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId/OpenIdAuthenticationConstants.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | namespace AspNet.Security.OpenId; 8 | 9 | public static class OpenIdAuthenticationConstants 10 | { 11 | public static class Aliases 12 | { 13 | public const string Ax = "ax"; 14 | } 15 | 16 | public static class Attributes 17 | { 18 | public const string Email = "http://axschema.org/contact/email"; 19 | public const string Firstname = "http://axschema.org/namePerson/first"; 20 | public const string Lastname = "http://axschema.org/namePerson/last"; 21 | public const string Name = "http://axschema.org/namePerson"; 22 | } 23 | 24 | public static class Headers 25 | { 26 | public const string XrdsLocation = "X-XRDS-Location"; 27 | } 28 | 29 | public static class Media 30 | { 31 | public const string Html = "text/html"; 32 | public const string Json = "application/json"; 33 | public const string Xhtml = "application/xhtml+xml"; 34 | public const string Xml = "text/xml"; 35 | public const string Xrds = "application/xrds+xml"; 36 | 37 | } 38 | 39 | public static class Metadata 40 | { 41 | public const string Content = "content"; 42 | public const string HttpEquiv = "http-equiv"; 43 | public const string Meta = "meta"; 44 | public const string XrdsLocation = "X-XRDS-Location"; 45 | } 46 | 47 | public static class Modes 48 | { 49 | public const string Cancel = "cancel"; 50 | public const string CheckAuthentication = "check_authentication"; 51 | public const string CheckIdSetup = "checkid_setup"; 52 | public const string Error = "error"; 53 | public const string FetchRequest = "fetch_request"; 54 | public const string IdRes = "id_res"; 55 | } 56 | 57 | public static class Namespaces 58 | { 59 | public const string Ax = "http://openid.net/srv/ax/1.0"; 60 | public const string OpenId = "http://specs.openid.net/auth/2.0"; 61 | } 62 | 63 | public static class Parameters 64 | { 65 | public const string ClaimedId = "claimed_id"; 66 | public const string Error = "error"; 67 | public const string Identity = "identity"; 68 | public const string IsValid = "is_valid"; 69 | public const string Mode = "mode"; 70 | public const string Namespace = "ns"; 71 | public const string Realm = "realm"; 72 | public const string Required = "required"; 73 | public const string ReturnTo = "return_to"; 74 | public const string State = "state"; 75 | } 76 | 77 | public static class Prefixes 78 | { 79 | public const string Ax = "openid.ax"; 80 | public const string Namespace = "openid.ns"; 81 | public const string OpenId = "openid"; 82 | public const string Type = "type"; 83 | } 84 | 85 | public static class Properties 86 | { 87 | public const string ReturnTo = ".return_to"; 88 | } 89 | 90 | public static class Suffixes 91 | { 92 | public const string Type = "type"; 93 | public const string Value = "value"; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId/OpenIdAuthenticationDefaults.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | namespace AspNet.Security.OpenId; 8 | 9 | /// 10 | /// Contains various constants used as default values 11 | /// for the OpenID authentication middleware. 12 | /// 13 | public static class OpenIdAuthenticationDefaults 14 | { 15 | /// 16 | /// Gets the default value associated with . 17 | /// 18 | public const string AuthenticationScheme = "OpenId"; 19 | 20 | /// 21 | /// Gets the default value associated with . 22 | /// 23 | public const string DisplayName = "OpenId"; 24 | 25 | /// 26 | /// Gets the default value associated with . 27 | /// 28 | public const string CallbackPath = "/signin-openid"; 29 | } 30 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId/OpenIdAuthenticationEvents.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using AspNet.Security.OpenId.Events; 8 | 9 | namespace AspNet.Security.OpenId; 10 | 11 | /// 12 | /// Specifies callback methods that the 13 | /// invokes to enable developer control over the OpenID2 authentication process. 14 | /// 15 | public class OpenIdAuthenticationEvents : RemoteAuthenticationEvents 16 | { 17 | /// 18 | /// Defines a notification invoked when the user is authenticated by the identity provider. 19 | /// 20 | public Func OnAuthenticated { get; set; } = context => Task.CompletedTask; 21 | 22 | /// 23 | /// Defines a notification invoked prior to redirecting to the identity provider. 24 | /// 25 | public Func OnRedirectToIdentityProvider { get; set; } = context => Task.CompletedTask; 26 | 27 | /// 28 | /// Defines a notification invoked when the user is authenticated by the identity provider. 29 | /// 30 | /// The context of the event carries information in and results out. 31 | /// Task to enable asynchronous execution 32 | public virtual Task Authenticated(OpenIdAuthenticatedContext context) => OnAuthenticated(context); 33 | 34 | /// 35 | /// Defines a notification invoked prior to redirecting to the identity provider. 36 | /// 37 | /// The context of the event carries information in and results out. 38 | /// Task to enable asynchronous execution 39 | public virtual Task RedirectToIdentityProvider(OpenIdRedirectContext context) => OnRedirectToIdentityProvider(context); 40 | } 41 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId/OpenIdAuthenticationExtensions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using System.Diagnostics.CodeAnalysis; 8 | using AspNet.Security.OpenId; 9 | using Microsoft.Extensions.DependencyInjection.Extensions; 10 | using Microsoft.Extensions.Options; 11 | using NotNullAttribute = JetBrains.Annotations.NotNullAttribute; 12 | 13 | namespace Microsoft.Extensions.DependencyInjection; 14 | 15 | public static class OpenIdAuthenticationExtensions 16 | { 17 | /// 18 | /// Adds to the specified 19 | /// , which enables OpenID 2.0 authentication capabilities. 20 | /// 21 | /// The authentication builder. 22 | /// The . 23 | public static AuthenticationBuilder AddOpenId([NotNull] this AuthenticationBuilder builder) 24 | { 25 | return builder.AddOpenId(OpenIdAuthenticationDefaults.AuthenticationScheme, options => { }); 26 | } 27 | 28 | /// 29 | /// Adds to the specified 30 | /// , which enables OpenID 2.0 authentication capabilities. 31 | /// 32 | /// The authentication builder. 33 | /// The delegate used to configure the OpenID 2.0 options. 34 | /// The . 35 | public static AuthenticationBuilder AddOpenId( 36 | [NotNull] this AuthenticationBuilder builder, 37 | [NotNull] Action configuration) 38 | { 39 | return builder.AddOpenId(OpenIdAuthenticationDefaults.AuthenticationScheme, configuration); 40 | } 41 | 42 | /// 43 | /// Adds to the specified 44 | /// , which enables OpenID 2.0 authentication capabilities. 45 | /// 46 | /// The authentication builder. 47 | /// The authentication scheme associated with this instance. 48 | /// The delegate used to configure the OpenID 2.0 options. 49 | /// The . 50 | public static AuthenticationBuilder AddOpenId( 51 | [NotNull] this AuthenticationBuilder builder, [NotNull] string scheme, 52 | [NotNull] Action configuration) 53 | { 54 | return builder.AddOpenId(scheme, OpenIdAuthenticationDefaults.DisplayName, configuration); 55 | } 56 | 57 | /// 58 | /// Adds to the specified 59 | /// , which enables OpenID 2.0 authentication capabilities. 60 | /// 61 | /// The authentication builder. 62 | /// The authentication scheme associated with this instance. 63 | /// The optional display name associated with this instance. 64 | /// The delegate used to configure the OpenID 2.0 options. 65 | /// The . 66 | public static AuthenticationBuilder AddOpenId( 67 | [NotNull] this AuthenticationBuilder builder, 68 | [NotNull] string scheme, [CanBeNull] string caption, 69 | [NotNull] Action configuration) 70 | { 71 | return builder.AddOpenId>(scheme, caption, configuration); 72 | } 73 | 74 | /// 75 | /// Adds to the specified 76 | /// , which enables OpenID 2.0 authentication capabilities. 77 | /// 78 | /// The authentication builder. 79 | /// The authentication scheme associated with this instance. 80 | /// The optional display name associated with this instance. 81 | /// The delegate used to configure the OpenID 2.0 options. 82 | /// The . 83 | public static AuthenticationBuilder AddOpenId( 84 | [NotNull] this AuthenticationBuilder builder, 85 | [NotNull] string scheme, [CanBeNull] string caption, 86 | [NotNull] Action configuration) 87 | where TOptions : OpenIdAuthenticationOptions, new() 88 | where THandler : OpenIdAuthenticationHandler 89 | { 90 | ArgumentNullException.ThrowIfNull(builder); 91 | ArgumentNullException.ThrowIfNull(configuration); 92 | ArgumentException.ThrowIfNullOrEmpty(scheme); 93 | 94 | // Note: TryAddEnumerable() is used here to ensure the initializer is only registered once. 95 | builder.Services.TryAddEnumerable( 96 | ServiceDescriptor.Singleton, 97 | OpenIdAuthenticationInitializer>()); 98 | 99 | return builder.AddRemoteScheme(scheme, caption, configuration); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId/OpenIdAuthenticationInitializer.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using System.ComponentModel; 8 | using AngleSharp.Html.Parser; 9 | using AspNet.Security.OpenId; 10 | using Microsoft.AspNetCore.DataProtection; 11 | using Microsoft.Extensions.Options; 12 | using Microsoft.IdentityModel.Protocols; 13 | 14 | namespace Microsoft.Extensions.DependencyInjection; 15 | 16 | /// 17 | /// Contains the methods required to ensure that the configuration used by 18 | /// the OpenID 2.0 generic handler is in a consistent and valid state. 19 | /// 20 | [EditorBrowsable(EditorBrowsableState.Never)] 21 | public class OpenIdAuthenticationInitializer([NotNull] IDataProtectionProvider dataProtectionProvider) : IPostConfigureOptions 22 | where TOptions : OpenIdAuthenticationOptions, new() 23 | where THandler : OpenIdAuthenticationHandler 24 | { 25 | /// 26 | /// Populates the default OpenID 2.0 handler options and ensure 27 | /// that the configuration is in a consistent and valid state. 28 | /// 29 | /// The authentication scheme associated with the handler instance. 30 | /// The options instance to initialize. 31 | public void PostConfigure([NotNull] string? name, [NotNull] TOptions options) 32 | { 33 | ArgumentNullException.ThrowIfNull(options); 34 | ArgumentException.ThrowIfNullOrEmpty(name); 35 | 36 | if (options.MaximumRedirections < 1) 37 | { 38 | throw new ArgumentException("The maximal number of redirections must be a non-zero positive number.", nameof(options)); 39 | } 40 | 41 | options.DataProtectionProvider ??= dataProtectionProvider; 42 | 43 | if (options.StateDataFormat == null) 44 | { 45 | var protector = options.DataProtectionProvider.CreateProtector( 46 | nameof(OpenIdAuthenticationHandler), name); 47 | 48 | options.StateDataFormat = new PropertiesDataFormat(protector); 49 | } 50 | 51 | options.HtmlParser ??= new HtmlParser(); 52 | 53 | if (options.Backchannel == null) 54 | { 55 | #pragma warning disable CA2000 56 | options.Backchannel = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler()); 57 | #pragma warning restore CA2000 58 | options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("ASP.NET Core OpenID 2.0 middleware"); 59 | options.Backchannel.Timeout = options.BackchannelTimeout; 60 | options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB 61 | } 62 | 63 | if (options.ConfigurationManager == null) 64 | { 65 | if (options.Configuration != null) 66 | { 67 | if (string.IsNullOrEmpty(options.Configuration.AuthenticationEndpoint)) 68 | { 69 | throw new ArgumentException("The authentication endpoint address cannot be null or empty.", nameof(options)); 70 | } 71 | 72 | options.ConfigurationManager = new StaticConfigurationManager(options.Configuration); 73 | } 74 | 75 | else 76 | { 77 | if (options.Authority == null && options.MetadataAddress == null) 78 | { 79 | throw new ArgumentException("The authority or an absolute metadata endpoint address must be provided.", nameof(options)); 80 | } 81 | 82 | if (options.MetadataAddress == null) 83 | { 84 | options.MetadataAddress = options.Authority!; 85 | } 86 | 87 | if (!options.MetadataAddress.IsAbsoluteUri) 88 | { 89 | if (options.Authority == null || !options.Authority.IsAbsoluteUri) 90 | { 91 | throw new ArgumentException("The authority must be provided and must be an absolute URL.", nameof(options)); 92 | } 93 | 94 | if (!string.IsNullOrEmpty(options.Authority.Fragment) || !string.IsNullOrEmpty(options.Authority.Query)) 95 | { 96 | throw new ArgumentException("The authority cannot contain a fragment or a query string.", nameof(options)); 97 | } 98 | 99 | if (!options.Authority.OriginalString.EndsWith('/')) 100 | { 101 | options.Authority = new Uri(options.Authority.OriginalString + "/", UriKind.Absolute); 102 | } 103 | 104 | options.MetadataAddress = new Uri(options.Authority, options.MetadataAddress); 105 | } 106 | 107 | if (options.RequireHttpsMetadata && !options.MetadataAddress.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase)) 108 | { 109 | throw new ArgumentException("The metadata endpoint address must be a HTTPS URL when " + 110 | "'RequireHttpsMetadata' is not set to 'false'.", nameof(options)); 111 | } 112 | 113 | options.ConfigurationManager = new ConfigurationManager( 114 | options.MetadataAddress?.AbsoluteUri ?? options.Authority!.AbsoluteUri, 115 | new OpenIdAuthenticationConfiguration.Retriever(options.Backchannel, options.HtmlParser) 116 | { 117 | MaximumRedirections = options.MaximumRedirections 118 | }, 119 | new HttpDocumentRetriever(options.Backchannel) { RequireHttps = options.RequireHttpsMetadata }); 120 | } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/AspNet.Security.OpenId/OpenIdAuthenticationOptions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using AngleSharp.Html.Parser; 8 | using Microsoft.IdentityModel.Protocols; 9 | 10 | namespace AspNet.Security.OpenId; 11 | 12 | public class OpenIdAuthenticationOptions : RemoteAuthenticationOptions 13 | { 14 | public OpenIdAuthenticationOptions() 15 | { 16 | CallbackPath = OpenIdAuthenticationDefaults.CallbackPath; 17 | Events = new OpenIdAuthenticationEvents(); 18 | } 19 | 20 | /// 21 | /// Gets or sets the absolute URL of the OpenID 2.0 authentication server. 22 | /// Note: this property is ignored when 23 | /// or are set. 24 | /// 25 | public Uri? Authority { get; set; } 26 | 27 | /// 28 | /// Gets or sets the URL of the OpenID 2.0 authentication XRDS discovery document. 29 | /// When the URL is relative, must be set and absolute. 30 | /// Note: this property is ignored when 31 | /// or are set. 32 | /// 33 | public Uri? MetadataAddress { get; set; } 34 | 35 | /// 36 | /// Gets or sets a boolean indicating whether HTTPS is required to retrieve the XRDS discovery document. 37 | /// The default value is true. This option should be used only in development environments. 38 | /// Note: this property is ignored when or are set. 39 | /// 40 | public bool RequireHttpsMetadata { get; set; } = true; 41 | 42 | /// 43 | /// Gets or sets the configuration used by the OpenID 2.0 authentication middleware. 44 | /// Note: this property is ignored when is set. 45 | /// 46 | public OpenIdAuthenticationConfiguration? Configuration { get; set; } 47 | 48 | /// 49 | /// Gets or sets the configuration manager used by the OpenID 2.0 authentication middleware. 50 | /// 51 | public IConfigurationManager? ConfigurationManager { get; set; } 52 | 53 | /// 54 | /// Gets or sets the realm associated with this instance. 55 | /// A default value is automatically inferred from the 56 | /// current URL when this value is left to null. 57 | /// 58 | public string? Realm { get; set; } 59 | 60 | /// 61 | /// Gets or sets the default AX attributes added to the OpenID request. 62 | /// 63 | public IDictionary Attributes { get; } = new Dictionary 64 | { 65 | ["email"] = "http://axschema.org/contact/email", 66 | ["name"] = "http://axschema.org/namePerson", 67 | ["first"] = "http://axschema.org/namePerson/first", 68 | ["last"] = "http://axschema.org/namePerson/last", 69 | 70 | ["email2"] = "http://schema.openid.net/contact/email", 71 | ["name2"] = "http://schema.openid.net/namePerson", 72 | ["first2"] = "http://schema.openid.net/namePerson/first", 73 | ["last2"] = "http://schema.openid.net/namePerson/last" 74 | }; 75 | 76 | /// 77 | /// Gets or sets the events provider associated with this instance. 78 | /// 79 | public new OpenIdAuthenticationEvents Events 80 | { 81 | get { return (OpenIdAuthenticationEvents)base.Events; } 82 | set { base.Events = value!; } 83 | } 84 | 85 | /// 86 | /// Gets or sets the data format used to serialize the 87 | /// authentication properties used for the "state" parameter. 88 | /// 89 | public ISecureDataFormat? StateDataFormat { get; set; } 90 | 91 | /// 92 | /// Gets or sets the HTML parser used to parse discovery documents. 93 | /// 94 | public HtmlParser? HtmlParser { get; set; } 95 | 96 | /// 97 | /// Gets the maximal number of roundtrips that are allowed 98 | /// before the discovery process is automatically aborted. 99 | /// By default, this property is set to 5. 100 | /// 101 | public int MaximumRedirections { get; set; } = 5; 102 | } 103 | -------------------------------------------------------------------------------- /test/AspNet.Security.OpenId.Providers.Tests/AspNet.Security.OpenId.Providers.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | AspNet.Security.OpenId 5 | $(DefaultNetCoreTargetFramework) 6 | false 7 | true 8 | $(NoWarn);CA1707 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /test/AspNet.Security.OpenId.Providers.Tests/Infrastructure/HttpRequestInterceptionFilter.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using JustEat.HttpClientInterception; 8 | using Microsoft.Extensions.Http; 9 | 10 | namespace AspNet.Security.OpenId.Infrastructure; 11 | 12 | /// 13 | /// Registers an delegating handler to intercept HTTP requests made by the test application. 14 | /// 15 | internal sealed class HttpRequestInterceptionFilter(HttpClientInterceptorOptions options) : IHttpMessageHandlerBuilderFilter 16 | { 17 | public Action Configure(Action next) 18 | { 19 | return builder => 20 | { 21 | next(builder); 22 | builder.AdditionalHandlers.Add(options.CreateHttpMessageHandler()); 23 | }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/AspNet.Security.OpenId.Providers.Tests/Infrastructure/LoopbackRedirectHandler.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using System.Web; 8 | 9 | namespace AspNet.Security.OpenId.Infrastructure; 10 | 11 | /// 12 | /// A delegating HTTP handler that loops back HTTP requests to external login providers to the local sign-in endpoint. 13 | /// 14 | internal sealed class LoopbackRedirectHandler : DelegatingHandler 15 | { 16 | internal string? UserIdentity { get; set; } 17 | 18 | internal IDictionary? UserAttributes { get; set; } 19 | 20 | protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 21 | { 22 | var result = await base.SendAsync(request, cancellationToken); 23 | 24 | // Follow the redirects to external services, assuming they are OpenID Connect-based 25 | if (result.StatusCode == System.Net.HttpStatusCode.Found && 26 | !string.Equals(result.Headers.Location?.Host, "localhost", StringComparison.OrdinalIgnoreCase)) 27 | { 28 | // Rewrite the URI to loop back to the redirected URL to simulate the user having 29 | // successfully authenticated with the external login page they were redirected to. 30 | var queryStringServer = HttpUtility.ParseQueryString(result.Headers.Location!.Query); 31 | 32 | string location = queryStringServer["openid.return_to"]!; 33 | 34 | var locationUri = new Uri(location, UriKind.Absolute); 35 | var queryStringSelf = HttpUtility.ParseQueryString(locationUri.Query); 36 | 37 | queryStringSelf.Add("code", "a6ed8e7f-471f-44f1-903b-65946475f351"); 38 | 39 | foreach (var key in queryStringServer.AllKeys) 40 | { 41 | if (key?.StartsWith("openid.", StringComparison.Ordinal) == true && 42 | !string.Equals(key, "openid.return_to", StringComparison.Ordinal)) 43 | { 44 | queryStringSelf.Add(key, queryStringServer[key]); 45 | } 46 | } 47 | 48 | // Add the appropriate parameters to satisfy the validation when looping back 49 | queryStringSelf["openid.mode"] = "id_res"; 50 | queryStringSelf["openid.return_to"] = location; 51 | 52 | if (!string.IsNullOrEmpty(UserIdentity)) 53 | { 54 | queryStringSelf["openid.claimed_id"] = UserIdentity; 55 | queryStringSelf["openid.identity"] = UserIdentity; 56 | } 57 | 58 | if (UserAttributes != null) 59 | { 60 | foreach (var pair in UserAttributes) 61 | { 62 | queryStringSelf[$"openid.ax.value.{pair.Key}"] = pair.Value; 63 | } 64 | } 65 | 66 | var builder = new UriBuilder(location) 67 | { 68 | Query = queryStringSelf.ToString(), 69 | }; 70 | 71 | using var redirectRequest = new HttpRequestMessage(request.Method, builder.Uri); 72 | 73 | // Forward on the headers and cookies 74 | foreach (var header in result.Headers) 75 | { 76 | redirectRequest.Headers.Add(header.Key, header.Value); 77 | } 78 | 79 | redirectRequest.Headers.Add("Cookie", result.Headers.GetValues("Set-Cookie")); 80 | 81 | // Follow the redirect URI 82 | return await base.SendAsync(redirectRequest, cancellationToken); 83 | } 84 | 85 | return result; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /test/AspNet.Security.OpenId.Providers.Tests/Infrastructure/Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | namespace AspNet.Security.OpenId.Infrastructure; 8 | 9 | /// 10 | /// A stub class representing the program class for the test application. 11 | /// 12 | public sealed class Program 13 | { 14 | } 15 | -------------------------------------------------------------------------------- /test/AspNet.Security.OpenId.Providers.Tests/Steam/SteamTests.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 3 | * See https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers 4 | * for more information concerning the license and the contributors participating to this project. 5 | */ 6 | 7 | using Microsoft.Extensions.DependencyInjection; 8 | 9 | namespace AspNet.Security.OpenId.Steam; 10 | 11 | public class SteamTests : OpenIdTests 12 | { 13 | public SteamTests(ITestOutputHelper outputHelper) 14 | { 15 | OutputHelper = outputHelper; 16 | Interceptor.ThrowOnMissingRegistration = true; 17 | 18 | UserAttributes["email"] = "john@john-smith.local"; 19 | UserAttributes["first"] = "John"; 20 | UserAttributes["namePerson"] = "John Smith"; 21 | } 22 | 23 | public override string DefaultScheme => SteamAuthenticationDefaults.AuthenticationScheme; 24 | 25 | public override string UserIdentity => "https://steamcommunity.com/openid/id/my-id"; 26 | 27 | protected internal override void RegisterAuthentication(AuthenticationBuilder builder) 28 | { 29 | builder.AddSteam(options => 30 | { 31 | ConfigureDefaults(builder, options); 32 | options.ApplicationKey = "steam-application-key"; 33 | }); 34 | } 35 | 36 | [Theory] 37 | [InlineData(ClaimTypes.NameIdentifier, "https://steamcommunity.com/openid/id/my-id")] 38 | [InlineData(ClaimTypes.Name, "John Smith")] 39 | [InlineData(ClaimTypes.Email, "john@john-smith.local")] 40 | [InlineData(ClaimTypes.GivenName, "John")] 41 | public async Task Can_Sign_In_Using_Steam(string claimType, string claimValue) 42 | { 43 | // Arrange 44 | using var server = CreateTestServer(); 45 | 46 | // Act 47 | var claims = await AuthenticateUserAsync(server); 48 | 49 | // Assert 50 | AssertClaim(claims, claimType, claimValue); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /test/AspNet.Security.OpenId.Providers.Tests/Steam/bundle.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/justeat/httpclient-interception/master/src/HttpClientInterception/Bundles/http-request-bundle-schema.json", 3 | "items": [ 4 | { 5 | "uri": "https://steamcommunity.com/openid/", 6 | "contentString": "http://specs.openid.net/auth/2.0/serverhttps://steamcommunity.com/openid/login", 7 | "contentHeaders": { 8 | "content-type": [ "application/xrds+xml" ] 9 | } 10 | }, 11 | { 12 | "uri": "https://steamcommunity.com/openid/login", 13 | "method": "POST", 14 | "contentString": "is_valid:true" 15 | }, 16 | { 17 | "uri": "https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=steam-application-key&steamids=my-id", 18 | "contentFormat": "json", 19 | "contentJson": { 20 | "response": { 21 | "players": [ 22 | { 23 | "steamid": "my-id", 24 | "personaname": "John Smith" 25 | } 26 | ] 27 | } 28 | } 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /test/AspNet.Security.OpenId.Providers.Tests/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "methodDisplay": "method" 3 | } 4 | --------------------------------------------------------------------------------