diff --git a/.github/run_esrp_signing.py b/.github/run_esrp_signing.py deleted file mode 100644 index be5a0f222..000000000 --- a/.github/run_esrp_signing.py +++ /dev/null @@ -1,135 +0,0 @@ -import argparse -import json -import os -import glob -import pprint -import subprocess -import sys -import re - -parser = argparse.ArgumentParser(description='Sign binaries for Windows, macOS, and Linux') -parser.add_argument('path', help='Path to file for signing') -parser.add_argument('keycode', help='Platform-specific key code for signing') -parser.add_argument('opcode', help='Platform-specific operation code for signing') -# Setting nargs=argparse.REMAINDER allows us to pass in params that begin with `--` -parser.add_argument('--params', nargs=argparse.REMAINDER, help='Parameters for signing') -args = parser.parse_args() - -esrp_tool = os.path.join("esrp", "tools", "EsrpClient.exe") - -aad_id = os.environ['AZURE_AAD_ID'].strip() -workspace = os.environ['GITHUB_WORKSPACE'].strip() - -source_location = args.path -files = glob.glob(os.path.join(source_location, "*")) - -print("Found files:") -pprint.pp(files) - -auth_json = { - "Version": "1.0.0", - "AuthenticationType": "AAD_CERT", - "TenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47", - "ClientId": f"{aad_id}", - "AuthCert": { - "SubjectName": f"CN={aad_id}.microsoft.com", - "StoreLocation": "LocalMachine", - "StoreName": "My", - "SendX5c" : "true" - }, - "RequestSigningCert": { - "SubjectName": f"CN={aad_id}", - "StoreLocation": "LocalMachine", - "StoreName": "My" - } -} - -input_json = { - "Version": "1.0.0", - "SignBatches": [ - { - "SourceLocationType": "UNC", - "SourceRootDirectory": source_location, - "DestinationLocationType": "UNC", - "DestinationRootDirectory": workspace, - "SignRequestFiles": [], - "SigningInfo": { - "Operations": [ - { - "KeyCode": f"{args.keycode}", - "OperationCode": f"{args.opcode}", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0", - } - ] - } - } - ] -} - -# add files to sign -for f in files: - name = os.path.basename(f) - input_json["SignBatches"][0]["SignRequestFiles"].append( - { - "SourceLocation": name, - "DestinationLocation": os.path.join("signed", name), - } - ) - -# add parameters to input.json (e.g. enabling the hardened runtime for macOS) -if args.params is not None: - i = 0 - while i < len(args.params): - input_json["SignBatches"][0]["SigningInfo"]["Operations"][0]["Parameters"][args.params[i]] = args.params[i + 1] - i += 2 - -policy_json = { - "Version": "1.0.0", - "Intent": "production release", - "ContentType": "binary", -} - -configs = [ - ("auth.json", auth_json), - ("input.json", input_json), - ("policy.json", policy_json), -] - -for filename, data in configs: - with open(filename, 'w') as fp: - json.dump(data, fp) - -# Run ESRP Client -esrp_out = "esrp_out.json" -result = subprocess.run( - [esrp_tool, "sign", - "-a", "auth.json", - "-i", "input.json", - "-p", "policy.json", - "-o", esrp_out, - "-l", "Verbose"], - capture_output=True, - text=True, - cwd=workspace) - -# Scrub log before printing -log = re.sub(r'^.+Uploading.*to\s*destinationUrl\s*(.+?),.+$', - '***', - result.stdout, - flags=re.IGNORECASE|re.MULTILINE) -print(log) - -if result.returncode != 0: - print("Failed to run ESRPClient.exe") - sys.exit(1) - -if os.path.isfile(esrp_out): - print("ESRP output json:") - with open(esrp_out, 'r') as fp: - pprint.pp(json.load(fp)) - -for file in files: - if os.path.isfile(os.path.join("signed", file)): - print(f"Success!\nSigned {file}") \ No newline at end of file diff --git a/.github/set_up_esrp.ps1 b/.github/set_up_esrp.ps1 deleted file mode 100644 index abe9183e0..000000000 --- a/.github/set_up_esrp.ps1 +++ /dev/null @@ -1,12 +0,0 @@ -# Install ESRP client -az storage blob download --file esrp.zip --auth-mode login --account-name $env:AZURE_STORAGE_ACCOUNT --container $env:AZURE_STORAGE_CONTAINER --name $env:ESRP_TOOL -Expand-Archive -Path esrp.zip -DestinationPath .\esrp - -# Install certificates -az keyvault secret download --vault-name "$env:AZURE_VAULT" --name "$env:AUTH_CERT" --file out.pfx -certutil -f -importpfx out.pfx -Remove-Item out.pfx - -az keyvault secret download --vault-name "$env:AZURE_VAULT" --name "$env:REQUEST_SIGNING_CERT" --file out.pfx -certutil -f -importpfx out.pfx -Remove-Item out.pfx \ No newline at end of file diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f9b3edea2..dc252805a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -24,9 +24,14 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v4.0.0 + with: + dotnet-version: 8.0.x + # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} @@ -34,4 +39,4 @@ jobs: dotnet build - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 7562447fc..1b83a990d 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -19,9 +19,9 @@ jobs: - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 6.0.201 + dotnet-version: 8.0.x - name: Install dependencies run: dotnet restore @@ -42,7 +42,7 @@ jobs: mv out/windows/Installer.Windows/bin/Release/net472/gcm*.exe artifacts/ - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: win-x86 path: | @@ -59,9 +59,9 @@ jobs: - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 6.0.201 + dotnet-version: 8.0.x - name: Install dependencies run: dotnet restore @@ -80,7 +80,7 @@ jobs: mv out/linux/Packaging.Linux/Release/tar/*.tar.gz artifacts/ - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: linux-x64 path: | @@ -100,9 +100,9 @@ jobs: - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 6.0.201 + dotnet-version: 8.0.x - name: Install dependencies run: dotnet restore @@ -125,7 +125,7 @@ jobs: mv out/osx/Installer.Mac/pkg/Release/gcm*.pkg artifacts/ - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.runtime }} path: | diff --git a/.github/workflows/lint-docs.yml b/.github/workflows/lint-docs.yml index cbc4b241e..4cf4c4b70 100644 --- a/.github/workflows/lint-docs.yml +++ b/.github/workflows/lint-docs.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: DavidAnson/markdownlint-cli2-action@ed4dec634fd2ef689c7061d5647371d8248064f1 + - uses: DavidAnson/markdownlint-cli2-action@b4c9feab76d8025d1e83c653fa3990936df0e6c8 with: globs: | "**/*.md" @@ -35,7 +35,7 @@ jobs: - name: Run link checker # For any troubleshooting, see: # https://github.com/lycheeverse/lychee/blob/master/docs/TROUBLESHOOTING.md - uses: lycheeverse/lychee-action@ec3ed119d4f44ad2673a7232460dc7dff59d2421 + uses: lycheeverse/lychee-action@c053181aa0c3d17606addfe97a9075a32723548a with: # user-agent: if a user agent is not specified, some websites (e.g. diff --git a/.github/workflows/maintainer-absence.yml b/.github/workflows/maintainer-absence.yml index 33c93f0ba..433cb0f7e 100644 --- a/.github/workflows/maintainer-absence.yml +++ b/.github/workflows/maintainer-absence.yml @@ -18,7 +18,7 @@ jobs: name: create-issue runs-on: ubuntu-latest steps: - - uses: actions/github-script@v6 + - uses: actions/github-script@v7 with: script: | const startDate = new Date('${{ github.event.inputs.startDate }}'); diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 67e407c0a..4cdda4e4a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,9 +35,9 @@ jobs: - uses: actions/checkout@v4 - name: Set up .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Build run: | @@ -130,7 +130,7 @@ jobs: --keychain-profile="$N4" - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: macos-${{ matrix.runtime }}-artifacts path: | @@ -150,9 +150,9 @@ jobs: - uses: actions/checkout@v4 - name: Set up .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Build run: | @@ -170,14 +170,14 @@ jobs: -SymbolOutput $env:GITHUB_WORKSPACE\symbols - name: Log into Azure - uses: azure/login@v1 + uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Sign payload files with Azure Code Signing - uses: azure/azure-code-signing-action@v0.2.21 + uses: azure/azure-code-signing-action@v0.3.1 with: endpoint: https://wus2.codesigning.azure.net/ code-signing-account-name: git-fundamentals-signing @@ -190,9 +190,9 @@ jobs: # The Azure Code Signing action overrides the .NET version, so we reset it. - name: Set up .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Build with signed payload run: | @@ -204,7 +204,7 @@ jobs: -Destination $env:GITHUB_WORKSPACE\installers - name: Sign installers with Azure Code Signing - uses: azure/azure-code-signing-action@v0.2.21 + uses: azure/azure-code-signing-action@v0.3.1 with: endpoint: https://wus2.codesigning.azure.net/ code-signing-account-name: git-fundamentals-signing @@ -216,7 +216,7 @@ jobs: timestamp-digest: SHA256 - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: windows-artifacts path: | @@ -236,9 +236,9 @@ jobs: - uses: actions/checkout@v4 - name: Set up .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Build run: dotnet build --configuration=LinuxRelease @@ -248,7 +248,7 @@ jobs: dotnet test --configuration=LinuxRelease - name: Log into Azure - uses: azure/login@v1 + uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -295,7 +295,7 @@ jobs: --detach-sig gcm-linux_amd64.$version.tar.gz - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: linux-artifacts path: | @@ -314,16 +314,16 @@ jobs: - uses: actions/checkout@v4 - name: Set up .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Build .NET tool run: | src/shared/DotnetTool/layout.sh --configuration=Release - name: Upload .NET tool artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: tmp.dotnet-tool-build path: | @@ -331,7 +331,6 @@ jobs: dotnet-tool-payload-sign: name: Sign .NET tool payload - # ESRP service requires signing to run on Windows runs-on: windows-latest environment: release needs: dotnet-tool-build @@ -339,56 +338,51 @@ jobs: - uses: actions/checkout@v4 - name: Download payload - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: tmp.dotnet-tool-build - - name: Zip unsigned payload - shell: pwsh - run: | - Compress-Archive -Path payload payload/payload.zip - cd payload - Get-ChildItem -Exclude payload.zip | Remove-Item -Recurse -Force - - name: Log into Azure - uses: azure/login@v1 + uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - - name: Set up ESRP client - shell: pwsh + - name: Download/extract Sign CLI tool env: - AZURE_VAULT: ${{ secrets.AZURE_VAULT }} - AZURE_STORAGE_ACCOUNT: ${{ secrets.AZURE_STORAGE_ACCOUNT }} - AZURE_STORAGE_CONTAINER: ${{ secrets.AZURE_STORAGE_CONTAINER }} - ESRP_TOOL: ${{ secrets.ESRP_TOOL }} - AUTH_CERT: ${{ secrets.AZURE_VAULT_AUTH_CERT_NAME }} - REQUEST_SIGNING_CERT: ${{ secrets.AZURE_VAULT_REQUEST_SIGNING_CERT_NAME }} + AST: ${{ secrets.AZURE_STORAGE_ACCOUNT }} + ASC: ${{ secrets.AZURE_STORAGE_CONTAINER }} + SCT: ${{ secrets.SIGN_CLI_TOOL }} run: | - .github\set_up_esrp.ps1 + az storage blob download --file sign-cli.zip --auth-mode login ` + --account-name $env:AST --container-name $env:ASC --name $env:SCT + Expand-Archive -Path sign-cli.zip -DestinationPath .\sign-cli - - name: Run ESRP client - shell: pwsh + - name: Sign payload env: - AZURE_AAD_ID: ${{ secrets.AZURE_AAD_ID }} - NUGET_KEY_CODE: ${{ secrets.NUGET_KEY_CODE }} - NUGET_OPERATION_CODE: ${{ secrets.NUGET_OPERATION_CODE }} + ACST: ${{ secrets.AZURE_TENANT_ID }} + ACSI: ${{ secrets.AZURE_CLIENT_ID }} + ACSS: ${{ secrets.AZURE_CLIENT_SECRET }} run: | - python .github\run_esrp_signing.py payload ` - $env:NUGET_KEY_CODE $env:NUGET_OPERATION_CODE + ./sign-cli/sign.exe code azcodesign payload/* ` + -acsu https://wus2.codesigning.azure.net/ ` + -acsa git-fundamentals-signing ` + -acscp git-fundamentals-windows-signing ` + -d "Git Fundamentals Windows Signing Certificate" ` + -u "https://github.com/git-ecosystem/git-credential-manager" ` + -acst $env:ACST ` + -acsi $env:ACSI ` + -acss $env:ACSS - name: Lay out signed payload, images, and symbols shell: bash run: | mkdir dotnet-tool-payload-sign - rm -rf payload - mv images payload.sym -t dotnet-tool-payload-sign - unzip signed/payload.zip -d dotnet-tool-payload-sign + mv images payload.sym payload -t dotnet-tool-payload-sign - name: Upload signed payload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: dotnet-tool-payload-sign path: | @@ -402,15 +396,15 @@ jobs: - uses: actions/checkout@v4 - name: Download signed payload - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: dotnet-tool-payload-sign path: signed - name: Set up .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Package tool run: | @@ -419,7 +413,7 @@ jobs: --publish-dir=$(pwd)/signed - name: Upload unsigned package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: tmp.dotnet-tool-package-unsigned path: | @@ -427,7 +421,6 @@ jobs: dotnet-tool-sign: name: Sign .NET tool package - # ESRP service requires signing to run on Windows runs-on: windows-latest environment: release needs: dotnet-tool-pack @@ -435,57 +428,49 @@ jobs: - uses: actions/checkout@v4 - name: Download unsigned package - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: tmp.dotnet-tool-package-unsigned path: nupkg - - name: Zip unsigned package - shell: pwsh - run: | - Compress-Archive -Path nupkg/*.nupkg nupkg/gcm-nupkg.zip - cd nupkg - Get-ChildItem -Exclude gcm-nupkg.zip | Remove-Item -Recurse -Force - - name: Log into Azure - uses: azure/login@v1 + uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - - name: Set up ESRP client - shell: pwsh + - name: Download/extract Sign CLI tool env: - AZURE_VAULT: ${{ secrets.AZURE_VAULT }} - AZURE_STORAGE_ACCOUNT: ${{ secrets.AZURE_STORAGE_ACCOUNT }} - AZURE_STORAGE_CONTAINER: ${{ secrets.AZURE_STORAGE_CONTAINER }} - ESRP_TOOL: ${{ secrets.ESRP_TOOL }} - AUTH_CERT: ${{ secrets.AZURE_VAULT_AUTH_CERT_NAME }} - REQUEST_SIGNING_CERT: ${{ secrets.AZURE_VAULT_REQUEST_SIGNING_CERT_NAME }} + AST: ${{ secrets.AZURE_STORAGE_ACCOUNT }} + ASC: ${{ secrets.AZURE_STORAGE_CONTAINER }} + SCT: ${{ secrets.SIGN_CLI_TOOL }} run: | - .github\set_up_esrp.ps1 + az storage blob download --file sign-cli.zip --auth-mode login ` + --account-name $env:AST --container-name $env:ASC --name $env:SCT + Expand-Archive -Path sign-cli.zip -DestinationPath .\sign-cli - name: Sign package - shell: pwsh env: - AZURE_AAD_ID: ${{ secrets.AZURE_AAD_ID }} - NUGET_KEY_CODE: ${{ secrets.NUGET_KEY_CODE }} - NUGET_OPERATION_CODE: ${{ secrets.NUGET_OPERATION_CODE }} - run: | - python .github\run_esrp_signing.py nupkg $env:NUGET_KEY_CODE $env:NUGET_OPERATION_CODE - - - name: Unzip signed package - shell: pwsh + ACST: ${{ secrets.AZURE_TENANT_ID }} + ACSI: ${{ secrets.AZURE_CLIENT_ID }} + ACSS: ${{ secrets.AZURE_CLIENT_SECRET }} run: | - Expand-Archive -LiteralPath signed\gcm-nupkg.zip -DestinationPath .\signed -Force - Remove-Item signed\gcm-nupkg.zip -Force + ./sign-cli/sign.exe code azcodesign nupkg/* ` + -acsu https://wus2.codesigning.azure.net/ ` + -acsa git-fundamentals-signing ` + -acscp git-fundamentals-windows-signing ` + -d "Git Fundamentals Windows Signing Certificate" ` + -u "https://github.com/git-ecosystem/git-credential-manager" ` + -acst $env:ACST ` + -acsi $env:ACSI ` + -acss $env:ACSS - name: Publish signed package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: dotnet-tool-sign - path: signed/*.nupkg + path: nupkg/*.nupkg # ================================ # Validate @@ -521,12 +506,12 @@ jobs: - uses: actions/checkout@v4 - name: Set up .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Download artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ matrix.component.artifact }} @@ -591,12 +576,12 @@ jobs: - uses: actions/checkout@v4 - name: Set up .NET - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.0.0 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Download artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 - name: Archive macOS payload and symbols run: | @@ -617,7 +602,7 @@ jobs: zip -jr win-x86-payload-and-symbols/gcm-win-x86-$version-symbols.zip windows-artifacts/symbols - name: Log into Azure - uses: azure/login@v1 + uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -630,7 +615,7 @@ jobs: | sed -e 's/^"//' -e 's/"$//' | base64 -d >gcm-public.asc mv gcm-public.asc linux-artifacts - - uses: actions/github-script@v6 + - uses: actions/github-script@v7 with: script: | const fs = require('fs'); diff --git a/.github/workflows/validate-install-from-source.yml b/.github/workflows/validate-install-from-source.yml index ff28dc85c..ca57d2daf 100644 --- a/.github/workflows/validate-install-from-source.yml +++ b/.github/workflows/validate-install-from-source.yml @@ -24,6 +24,7 @@ jobs: - image: tgagor/centos-stream - image: redhat/ubi8 - image: alpine + - image: alpine:3.14.10 - image: opensuse/leap - image: opensuse/tumbleweed - image: registry.suse.com/suse/sle15:15.4.27.11.31 diff --git a/.vscode/launch.json b/.vscode/launch.json index af72a8e27..d9b004b86 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/out/shared/Git-Credential-Manager/bin/Debug/net7.0/git-credential-manager.dll", + "program": "${workspaceFolder}/out/shared/Git-Credential-Manager/bin/Debug/net8.0/git-credential-manager.dll", "args": ["get"], "cwd": "${workspaceFolder}/out/shared/Git-Credential-Manager", "console": "integratedTerminal", @@ -22,7 +22,7 @@ "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/out/shared/Git-Credential-Manager/bin/Debug/net7.0/git-credential-manager.dll", + "program": "${workspaceFolder}/out/shared/Git-Credential-Manager/bin/Debug/net8.0/git-credential-manager.dll", "args": ["store"], "cwd": "${workspaceFolder}/out/shared/Git-Credential-Manager", "console": "integratedTerminal", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index e47892848..c559b17b8 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -56,7 +56,7 @@ "type": "shell", "group": "test", "args": [ - "~/.nuget/packages/reportgenerator/*/*/net7.0/ReportGenerator.dll", + "~/.nuget/packages/reportgenerator/*/*/net8.0/ReportGenerator.dll", "-reports:${workspaceFolder}/**/TestResults/**/coverage.cobertura.xml", "-targetdir:${workspaceFolder}/out/code-coverage" ], @@ -71,7 +71,7 @@ "type": "shell", "group": "test", "args": [ - "${env:USERROFILE}/.nuget/packages/reportgenerator/*/*/net7.0/ReportGenerator.dll", + "${env:USERROFILE}/.nuget/packages/reportgenerator/*/*/net8.0/ReportGenerator.dll", "-reports:${workspaceFolder}/**/TestResults/**/coverage.cobertura.xml", "-targetdir:${workspaceFolder}/out/code-coverage" ], diff --git a/VERSION b/VERSION index 42dece39c..e975051fc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4.1.0 +2.5.0.0 diff --git a/build/GCM.MSBuild.csproj b/build/GCM.MSBuild.csproj index 02f5a8444..3df4909e6 100644 --- a/build/GCM.MSBuild.csproj +++ b/build/GCM.MSBuild.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 false diff --git a/docs/README.md b/docs/README.md index 3c08cfdfc..716c106ee 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,18 +11,19 @@ The following are links to GCM user support documentation: - [Credential stores][gcm-credstores] - [Host provider specification][gcm-host-provider] - [Azure Repos OAuth tokens][gcm-azure-tokens] +- [Azure Managed Identities and Service Principals][gcm-misp] - [GitLab support][gcm-gitlab] - [Generic OAuth support][gcm-oauth] [gcm-azure-tokens]: azrepos-users-and-tokens.md [gcm-config]: configuration.md [gcm-credstores]: credstores.md -[gcm-dev]: development.md [gcm-enterprise-config]: enterprise-config.md [gcm-env]: environment.md [gcm-faq]: faq.md [gcm-gitlab]: gitlab.md [gcm-host-provider]: hostprovider.md +[gcm-misp]: azrepos-misp.md [gcm-net-config]: netconfig.md [gcm-oauth]: generic-oauth.md [gcm-usage]: usage.md diff --git a/docs/azrepos-misp.md b/docs/azrepos-misp.md new file mode 100644 index 000000000..6c4c508fe --- /dev/null +++ b/docs/azrepos-misp.md @@ -0,0 +1,126 @@ +# Azure Managed Identities and Service Principals + +Git Credential Manager supports Managed Identities and Service Principals for +authentication with Azure Repos. This document provides an overview of Managed +Identities and Service Principals and how to use them with GCM. + +## Managed Identities + +Azure Managed Identities can be used to authenticate and authorize applications +and services to access Azure resources. Managed Identities are a secure way to +access Azure resources without needing to store credentials in code or +configuration files. + +There are two types of Managed Identities: + +**System-assigned** + +System-assigned Managed Identities are tied to a specific Azure resource, such +as a Virtual Machine or App Service. When a system-assigned Managed Identity is +enabled, Azure creates an identity for the resource in the Azure AD tenant +that's trusted by the subscription. The lifecycle of the identity is tied to the +resource to which it's assigned. + +**User-assigned** + +User-assigned Managed Identities are created as standalone Azure resources and +can be assigned to one or more Azure resources. This allows you to use the same +Managed Identity across multiple resources. + +You can read more about Managed Identities in the +[Azure documentation][az-mi]. + +### How to configure Managed Identities + +In order to use a Managed Identity with GCM, you need to ensure that the Managed +Identity has the necessary permissions to access the Azure Repos repository. + +You can read more about how to configure Managed Identities in the +[Azure Repos documentation][azdo-misp]. + +Once you have configured the Managed Identity, you can use it with GCM by simply +setting one of the following environment variables or Git configuration options: + +**Git configuration:** [`credential.azreposManagedIdentity`][gcm-mi-config] + +**Environment variable:** [`GCM_AZREPOS_MANAGEDIDENTITY`][gcm-mi-env] + +Value|Description +-|- +`system`|System-Assigned Managed Identity +`[guid]`|User-Assigned Managed Identity with the specified client ID +`id://[guid]`|User-Assigned Managed Identity with the specified client ID +`resource://[guid]`|User-Assigned Managed Identity for the associated resource + +You can obtain the `[guid]` from the Azure Portal or by using the Azure CLI +to inspect the Managed Identity or resource. + +## Service Principals + +Azure Service Principals are used to authenticate and authorize applications and +services to access Azure resources. Service Principals are similar in many ways +to Managed Identities (in fact Service Principals are used under the hood to +implement Managed Identities), but they have expliclty defined credentials that +are not managed by Azure. + +There are a number of different ways to create and configure Service Principals, +including using the Azure Portal or Azure CLI. You can read more about Service +Principals in the [Azure documentation][az-sp]. + +### How to configure Service Principals + +Much like with Managed Identities, to use a Service Principal with GCM you first +need to ensure that the principal has the necessary permissions to access the +Azure Repos repository. + +You can read more about how to configure Service Principals in the +[Azure Repos documentation][azdo-misp]. + +Once you have configured the Service Principal, you can use it with GCM by +setting one of the following environment variables or Git configuration options: + +**Git configuration:** [`credential.azreposServicePrincipal`][gcm-sp-config] + +**Environment variable:** [`GCM_AZREPOS_SERVICE_PRINCIPAL`][gcm-sp-env] + +The format of the value for these options must be in the format: + +```text +{tenantId}/{clientId} +``` + +Where `{tenantId}` is the Azure tenant ID and `{clientId}` is the client ID of +the Service Principal. These values can be found in the Azure Portal or by using +the Azure CLI to inspect the Service Principal. + +#### Authentication with Service Principals + +When using a Service Principal with GCM, you will also need to provide the +client secret or certificate that is associated with the Service Principal. + +You can provide the client secret or certificate to GCM by setting one of the +following environment variables or Git configuration options. + +Type|Git Configuration|Environment Variable +-|-|- +Client Secret|[`credential.azreposServicePrincipalSecret`][gcm-sp-secret-config]|[`GCM_AZREPOS_SP_SECRET`][gcm-sp-secret-env] +Certificate|[`credential.azreposServicePrincipalCertificateThumbprint`][gcm-sp-cert-config]|[`GCM_AZREPOS_SP_CERT_THUMBPRINT`][gcm-sp-cert-env] + +The value for these options should be the client secret or the thumbrint of the +certificate that is associated with the Service Principal. + +The certificate itself should be installed on the machine where GCM is running +and should be installed in personal store the certificate store for either the +current user or the local machine. + +[az-mi]: https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview +[az-sp]: https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals?tabs=browser +[azdo-misp]: https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity?view=azure-devops +[gcm-mi-config]: https://gh.io/gcm/config#credentialazreposmanagedidentity +[gcm-mi-env]: https://gh.io/gcm/env#GCM_AZREPOS_MANAGEDIDENTITY +[gcm-sp-config]: https://gh.io/gcm/config#credentialazreposserviceprincipal +[gcm-sp-env]: https://gh.io/gcm/env#GCM_AZREPOS_SERVICE_PRINCIPAL +[gcm-sp-secret-config]: https://gh.io/gcm/config#credentialazreposserviceprincipalsecret +[gcm-sp-secret-env]: https://gh.io/gcm/env#GCM_AZREPOS_SP_SECRET +[gcm-sp-cert-config]: https://gh.io/gcm/config#credentialazreposserviceprincipalcertificatethumbprint +[gcm-sp-cert-env]: https://gh.io/gcm/env#GCM_AZREPOS_SP_CERT_THUMBPRINT diff --git a/docs/development.md b/docs/development.md index 31350192a..7729556f9 100644 --- a/docs/development.md +++ b/docs/development.md @@ -209,13 +209,13 @@ HTML reports can be generated using ReportGenerator, this should be installed during the build process, from the command line: ```shell -dotnet ~/.nuget/packages/reportgenerator/*/*/net7.0/ReportGenerator.dll -reports:./**/TestResults/**/coverage.cobertura.xml -targetdir:./out/code-coverage +dotnet ~/.nuget/packages/reportgenerator/*/*/net8.0/ReportGenerator.dll -reports:./**/TestResults/**/coverage.cobertura.xml -targetdir:./out/code-coverage ``` or ```shell -dotnet {$env:USERPROFILE}/.nuget/packages/reportgenerator/*/*/net7.0/ReportGenerator.dll -reports:./**/TestResults/**/coverage.cobertura.xml -targetdir:./out/code-coverage +dotnet {$env:USERPROFILE}/.nuget/packages/reportgenerator/*/*/net8.0/ReportGenerator.dll -reports:./**/TestResults/**/coverage.cobertura.xml -targetdir:./out/code-coverage ``` Or via VSCode Terminal/Run Task: diff --git a/src/linux/Packaging.Linux/Packaging.Linux.csproj b/src/linux/Packaging.Linux/Packaging.Linux.csproj index 362ffc230..8b9755c78 100644 --- a/src/linux/Packaging.Linux/Packaging.Linux.csproj +++ b/src/linux/Packaging.Linux/Packaging.Linux.csproj @@ -3,7 +3,7 @@ - net7.0 + net8.0 false diff --git a/src/linux/Packaging.Linux/install-from-source.sh b/src/linux/Packaging.Linux/install-from-source.sh index 98fe7bc4d..be6ea1579 100755 --- a/src/linux/Packaging.Linux/install-from-source.sh +++ b/src/linux/Packaging.Linux/install-from-source.sh @@ -26,7 +26,7 @@ if [ -z "$installPrefix" ]; then fi # Ensure install directory exists -if [! -d "$installPrefix" ]; then +if [ ! -d "$installPrefix" ]; then echo "The folder $installPrefix does not exist" exit fi @@ -83,7 +83,7 @@ ensure_dotnet_installed() { if [ -z "$(verify_existing_dotnet_installation)" ]; then curl -LO https://dot.net/v1/dotnet-install.sh chmod +x ./dotnet-install.sh - bash -c "./dotnet-install.sh --channel 7.0" + bash -c "./dotnet-install.sh --channel 8.0" # Since we have to run the dotnet install script with bash, dotnet isn't # added to the process PATH, so we manually add it here. @@ -98,7 +98,7 @@ verify_existing_dotnet_installation() { sdks=$(dotnet --list-sdks | cut -c 1-3) # If we have a supported version installed, return. - supported_dotnet_versions="7.0" + supported_dotnet_versions="8.0" for v in $supported_dotnet_versions; do if [ $(echo $sdks | grep "$v") ]; then echo $sdks @@ -137,6 +137,10 @@ print_unsupported_distro() { echo "See https://gh.io/gcm/linux for details." } +version_at_least() { + [ "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ] +} + sudo_cmd= # If the user isn't root, we need to use `sudo` for certain commands @@ -157,7 +161,7 @@ case "$distribution" in # Install dotnet packages and dependencies if needed. if [ -z "$(verify_existing_dotnet_installation)" ]; then # First try to use native feeds (Ubuntu 22.04 and later). - if ! apt_install dotnet7; then + if ! apt_install dotnet8; then # If the native feeds fail, we fall back to # packages.microsoft.com. We begin by adding the dotnet package # repository/signing key. @@ -173,7 +177,7 @@ case "$distribution" in $sudo_cmd apt update $sudo_cmd apt install apt-transport-https -y $sudo_cmd apt update - $sudo_cmd apt install dotnet-sdk-7.0 dpkg-dev -y + $sudo_cmd apt install dotnet-sdk-8.0 dpkg-dev -y fi fi ;; @@ -189,7 +193,14 @@ case "$distribution" in $sudo_cmd apk update # Install dotnet/GCM dependencies. - install_packages apk add "curl git icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib which bash coreutils gcompat" + # Alpine 3.14 and earlier need libssl1.1, while later versions need libssl3. + if ( version_at_least "3.15" $version ) then + libssl_pkg="libssl3" + else + libssl_pkg="libssl1.1" + fi + + install_packages apk add "curl git icu-libs krb5-libs libgcc libintl $libssl_pkg libstdc++ zlib which bash coreutils gcompat" ensure_dotnet_installed ;; diff --git a/src/linux/Packaging.Linux/layout.sh b/src/linux/Packaging.Linux/layout.sh index 5f3ba8ca8..6679c39ca 100755 --- a/src/linux/Packaging.Linux/layout.sh +++ b/src/linux/Packaging.Linux/layout.sh @@ -38,7 +38,7 @@ GCM_SRC="$SRC/shared/Git-Credential-Manager" PROJ_OUT="$OUT/linux/Packaging.Linux" # Build parameters -FRAMEWORK=net7.0 +FRAMEWORK=net8.0 RUNTIME=linux-x64 # Perform pre-execution checks diff --git a/src/osx/Installer.Mac/Installer.Mac.csproj b/src/osx/Installer.Mac/Installer.Mac.csproj index e46022374..daabd20d4 100644 --- a/src/osx/Installer.Mac/Installer.Mac.csproj +++ b/src/osx/Installer.Mac/Installer.Mac.csproj @@ -3,7 +3,7 @@ - net7.0 + net8.0 false diff --git a/src/osx/Installer.Mac/layout.sh b/src/osx/Installer.Mac/layout.sh index 544b7e106..ad8e2cfc2 100755 --- a/src/osx/Installer.Mac/layout.sh +++ b/src/osx/Installer.Mac/layout.sh @@ -24,7 +24,7 @@ GCM_SRC="$SRC/shared/Git-Credential-Manager" GCM_UI_SRC="$SRC/shared/Git-Credential-Manager.UI.Avalonia" # Build parameters -FRAMEWORK=net7.0 +FRAMEWORK=net8.0 # Parse script arguments for i in "$@" diff --git a/src/shared/Atlassian.Bitbucket.Tests/Atlassian.Bitbucket.Tests.csproj b/src/shared/Atlassian.Bitbucket.Tests/Atlassian.Bitbucket.Tests.csproj index 0e3c94c22..d5d08797c 100644 --- a/src/shared/Atlassian.Bitbucket.Tests/Atlassian.Bitbucket.Tests.csproj +++ b/src/shared/Atlassian.Bitbucket.Tests/Atlassian.Bitbucket.Tests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 false true latest diff --git a/src/shared/Atlassian.Bitbucket/Atlassian.Bitbucket.csproj b/src/shared/Atlassian.Bitbucket/Atlassian.Bitbucket.csproj index af8285c72..6aab348f8 100644 --- a/src/shared/Atlassian.Bitbucket/Atlassian.Bitbucket.csproj +++ b/src/shared/Atlassian.Bitbucket/Atlassian.Bitbucket.csproj @@ -1,8 +1,8 @@  - net7.0 - net7.0;net472 + net8.0 + net8.0;net472 Atlassian.Bitbucket Atlassian.Bitbucket false diff --git a/src/shared/Atlassian.Bitbucket/UI/Views/CredentialsView.axaml b/src/shared/Atlassian.Bitbucket/UI/Views/CredentialsView.axaml index f74161a5c..717500b7b 100644 --- a/src/shared/Atlassian.Bitbucket/UI/Views/CredentialsView.axaml +++ b/src/shared/Atlassian.Bitbucket/UI/Views/CredentialsView.axaml @@ -29,7 +29,7 @@ Margin="0,10,0,0"/> - -