From d20de8aaf589b9f99aad02470f9d6909e1853498 Mon Sep 17 00:00:00 2001 From: ci Date: Mon, 25 May 2026 10:44:12 +0000 Subject: [PATCH 1/4] ci: install baseline CI gates (secret-scan + unicode-check + dependabot) Installed via 'sca ci --install' (SSOT templates): self-hosted JIT runners, URT cloned outside the workspace, sca pinned, gitleaks backstop. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/dependabot.yml | 6 ++ .github/workflows/secret-scan.yml | 81 +++++++++++++++++++++++++ .github/workflows/unicode-check.yml | 91 +++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/secret-scan.yml create mode 100644 .github/workflows/unicode-check.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5ace460 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml new file mode 100644 index 0000000..0eef568 --- /dev/null +++ b/.github/workflows/secret-scan.yml @@ -0,0 +1,81 @@ +name: secret-scan + +# Defense-in-depth secret scanning. SSOT (sca, distributed via PyPI) + +# independent backstop (gitleaks). Pattern changes happen in +# source-control-automation; cutting a release on tag push publishes a +# new wheel; consumers pin a version and bump deliberately. + +on: + push: + branches: [ main, master ] + pull_request: + workflow_dispatch: + +jobs: + sca-scan: + name: sca scan (single source of truth) + runs-on: [self-hosted, Linux] + steps: + - name: Checkout this repo + uses: actions/checkout@v5 + + - uses: actions/setup-python@v6 + with: + python-version: "3.12" + + - name: Install sca from PyPI + shell: bash + run: | + python -m pip install --upgrade pip + pip install aollivierre-sca==0.2.7 + + - name: Run sca scan against this repo + shell: bash + run: | + # exit codes: + # 0 = clean + # 1 = high-severity findings only (non-blocking; see threat model) + # 2 = critical findings -> fail the job + set +e + sca scan . --exclude tests --exclude __tests__ --exclude fixtures \ + --exclude spec --exclude test_data --exclude test-data + rc=$? + if [ $rc -ge 2 ]; then + echo "::error::sca found critical secret findings" + exit 1 + fi + echo "::notice::sca scan ok (exit=$rc; high-only is non-blocking)" + exit 0 + + gitleaks: + name: gitleaks (independent second opinion) + runs-on: [self-hosted, Linux] + steps: + - uses: actions/checkout@v5 + + - name: Install gitleaks + shell: bash + run: | + set -euo pipefail + VERSION=8.21.2 + curl -fsSL "https://github.com/gitleaks/gitleaks/releases/download/v${VERSION}/gitleaks_${VERSION}_linux_x64.tar.gz" \ + -o gitleaks.tar.gz + tar -xzf gitleaks.tar.gz gitleaks + sudo mv gitleaks /usr/local/bin/gitleaks + gitleaks version + + - name: Scan working tree + shell: bash + run: | + # --no-git: scan working tree only (sca scan above covered the + # committed state). + # --redact: never echo a secret value into CI logs. + # --verbose: show finding lines so triage is fast. + # --exit-code 1: any finding fails the job. + gitleaks detect \ + --source . \ + --no-banner \ + --no-git \ + --redact \ + --verbose \ + --exit-code 1 diff --git a/.github/workflows/unicode-check.yml b/.github/workflows/unicode-check.yml new file mode 100644 index 0000000..8c3e81b --- /dev/null +++ b/.github/workflows/unicode-check.yml @@ -0,0 +1,91 @@ +name: unicode-check + +on: + push: + branches: [ main, master ] + pull_request: + workflow_dispatch: + +# contents: write lets the auto-remediation step commit the ASCII-fixed +# files back to the branch. Pushes made with the default GITHUB_TOKEN do +# NOT re-trigger workflows, so the commit-back cannot loop. +permissions: + contents: write + +jobs: + ascii-check: + name: ascii-only via URT (single source of truth) + # Self-hosted (served by the JIT broker; see RUNNER_BROKER.md). NOT a + # GitHub-hosted runner: a billing-blocked free tier fails GitHub-hosted + # jobs at the billing gate before runner-label matching. + runs-on: [self-hosted, Linux] + steps: + - name: Checkout this repo + uses: actions/checkout@v5 + with: + # Check out the branch HEAD (not the PR merge ref) so the + # auto-remediation commit can be pushed back to it. + ref: ${{ github.head_ref || github.ref_name }} + + - uses: actions/setup-python@v6 + with: + python-version: "3.12" + + - name: Clone URT outside workspace (avoids scanning the scanner) + shell: bash + run: | + # Use $RUNNER_TEMP (per-job dir) instead of /tmp/_urt (shared + # on a self-hosted runner host). Concurrent ephemeral runners + # otherwise collide with `destination path already exists`. + rm -rf "$RUNNER_TEMP/_urt" + git clone --depth 1 https://github.com/aollivierre/UnicodeReplacementTool "$RUNNER_TEMP/_urt" + + - name: Remediate Unicode with URT (auto-fix in place) + shell: bash + run: | + # Fix mode (no --preview): rewrite any non-ASCII to ASCII. + # --no-backup: git history is the backup. Same pattern set as the + # verification pass below. Markdown is exempt (no *.md pattern). + python "$RUNNER_TEMP/_urt/unicode_replacer.py" \ + --yes --no-backup \ + . \ + --recursive \ + --pattern '*.py' '*.ps1' '*.psm1' '*.psd1' '*.toml' \ + '*.yml' '*.yaml' '*.sh' '*.bat' '*.cmd' + + - name: Commit and push remediation if anything changed + shell: bash + run: | + if [ -z "$(git status --porcelain)" ]; then + echo "unicode-check: already ASCII-clean; nothing to remediate." + exit 0 + fi + echo "unicode-check: URT rewrote non-ASCII characters; committing the fix back." + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add -A + git commit -m "style: auto-remediate Unicode -> ASCII via URT" + # Push back to the originating branch. GITHUB_TOKEN pushes do NOT + # re-trigger workflows, so this commit-back is loop-safe. + git push origin "HEAD:${{ github.head_ref || github.ref_name }}" + + - name: Verify ASCII-clean (gate) + shell: bash + run: | + set -o pipefail + python "$RUNNER_TEMP/_urt/unicode_replacer.py" \ + --preview \ + . \ + --recursive \ + --pattern '*.py' '*.ps1' '*.psm1' '*.psd1' '*.toml' \ + '*.yml' '*.yaml' '*.sh' '*.bat' '*.cmd' \ + | tee urt-preview.txt + + # URT prints "Files with Unicode: " in its summary. After the + # remediation step this should be 0; a non-zero count here means URT + # could not fully fix something -- fail the job so it gets eyes. + if grep -E "Files with Unicode: [1-9]" urt-preview.txt > /dev/null; then + echo "unicode-check: Unicode still present after remediation (unexpected)." + exit 1 + fi + echo "unicode-check: ASCII-clean." From ee796d6da8d9dd4472fbec25efda8ec64fbb1c97 Mon Sep 17 00:00:00 2001 From: ci Date: Mon, 25 May 2026 10:44:12 +0000 Subject: [PATCH 2/4] style: auto-remediate Unicode -> ASCII via URT Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Archive/test/secrets.test.psd1 | Bin 2288 -> 2302 bytes .../Archive/test2/MigrationConfig.psd1 | 2 +- DeviceMigration/MigrationConfig.psd1 | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DeviceMigration/Archive/test/secrets.test.psd1 b/DeviceMigration/Archive/test/secrets.test.psd1 index 593b3d1c10399cc84ffab41beb4178046bbbde19..f180e7e6f0377f1a67ce5b2f7d056f6ea81299b0 100644 GIT binary patch delta 206 zcmew$_)kzEI#k=u&CMkiMo(l~z{oXmu_}-_sSYGQhJpy?$ytmdj9ioJ8AbKE7`PY| zpwNcFg~6F2guxCdh7bkG+Az2>3mADPZd3&l*VTc<|4=;l* zT^O8!;;5n^JvI!k40#~&$rl;j89}7{W(%e~Hfdz-5QX}1r3X30)nM`<3;h|A7_y*- JBlyKY5ddq5AXfkY diff --git a/DeviceMigration/Archive/test2/MigrationConfig.psd1 b/DeviceMigration/Archive/test2/MigrationConfig.psd1 index 46c061e..22d43b3 100644 --- a/DeviceMigration/Archive/test2/MigrationConfig.psd1 +++ b/DeviceMigration/Archive/test2/MigrationConfig.psd1 @@ -1,4 +1,4 @@ -@{ +@{ MigrationPath = "C:\ProgramData\AADMigration" UseOneDriveKFM = $True diff --git a/DeviceMigration/MigrationConfig.psd1 b/DeviceMigration/MigrationConfig.psd1 index 46c061e..22d43b3 100644 --- a/DeviceMigration/MigrationConfig.psd1 +++ b/DeviceMigration/MigrationConfig.psd1 @@ -1,4 +1,4 @@ -@{ +@{ MigrationPath = "C:\ProgramData\AADMigration" UseOneDriveKFM = $True From e03293c86a92590303461a0ebf247b329fae33c7 Mon Sep 17 00:00:00 2001 From: ci Date: Mon, 25 May 2026 10:44:12 +0000 Subject: [PATCH 3/4] docs: add README Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..d5f1d88 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# IntuneDeviceMigration + +Device state migration from Workgroup/ADJ/EHJ to EJ + Intune Managed + +Part of the aollivierre tooling fleet. From 1a78cc7e8e203681751ba7b7508dd6208634ba28 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 25 May 2026 11:39:37 +0000 Subject: [PATCH 4/4] style: auto-remediate Unicode -> ASCII via URT --- .../test/CreateAndRegisterScheduledTask-TEST.test.ps1 | 6 +++--- .../Archive/test/Deploy-Application-Archive.test.ps1 | 2 +- .../Archive/test/Execute-MigrationToolkit-Archived.test.ps1 | 2 +- .../Archive/test2/CreateODSyncUtil.Task.test.ps1 | 4 ++-- DeviceMigration/Archive/test2/Deploy-Application.test.ps1 | 2 +- DeviceMigration/Files/ODSyncUtil/Get-ODStatusFromDLL.ps1 | 2 +- DeviceMigration/PSADT-Customizations/Deploy-Application.ps1 | 2 +- .../PSADT-Customizations/Deploy-Application.test.ps1 | 2 +- .../PSAppDeployToolkit/Examples/VLC/Deploy-Application.ps1 | 2 +- .../Examples/WinSCP/Deploy-Application.ps1 | 2 +- .../Toolkit/AppDeployToolkit/AppDeployToolkitExtensions.ps1 | 2 +- .../Toolkit/AppDeployToolkit/AppDeployToolkitHelp.ps1 | 2 +- .../Toolkit/AppDeployToolkit/AppDeployToolkitMain.ps1 | 2 +- .../PSAppDeployToolkit/Toolkit/Deploy-Application.ps1 | 2 +- .../PSAppDeployToolkit/Toolkit/Deploy-Application.test.ps1 | 2 +- 15 files changed, 18 insertions(+), 18 deletions(-) diff --git a/DeviceMigration/Archive/test/CreateAndRegisterScheduledTask-TEST.test.ps1 b/DeviceMigration/Archive/test/CreateAndRegisterScheduledTask-TEST.test.ps1 index 406e732..6e595ac 100644 --- a/DeviceMigration/Archive/test/CreateAndRegisterScheduledTask-TEST.test.ps1 +++ b/DeviceMigration/Archive/test/CreateAndRegisterScheduledTask-TEST.test.ps1 @@ -419,12 +419,12 @@ CreateAndRegisterScheduledTask @taskParams # - **Example Use Case:** If you want a task to run every day at 9:00 AM, you would set the `StartTime` to `"09:00:00"`. # ### Practical Differences: -# - **StartBoundary:** Controls when the task becomes eligible to run. It’s a one-time setting that dictates when the task can first start, often used with non-recurring tasks or as a gate for when recurring tasks can start. -# - **StartTime:** Controls the exact time on a daily or weekly basis when the task should be executed. It’s used for recurring tasks that need to start at the same time every day or on specific days of the week. +# - **StartBoundary:** Controls when the task becomes eligible to run. It[U+2019]s a one-time setting that dictates when the task can first start, often used with non-recurring tasks or as a gate for when recurring tasks can start. +# - **StartTime:** Controls the exact time on a daily or weekly basis when the task should be executed. It[U+2019]s used for recurring tasks that need to start at the same time every day or on specific days of the week. # ### Example Scenario: # If you want a task to start running every day at 9:00 AM but only start doing so from September 1, 2024, you would set: -# - `StartBoundary = "2024-09-01T00:00:00"` (the task won’t run before this date). +# - `StartBoundary = "2024-09-01T00:00:00"` (the task won[U+2019]t run before this date). # - `StartTime = "09:00:00"` (the task will run at 9:00 AM daily after September 1, 2024). # ### Conclusion: diff --git a/DeviceMigration/Archive/test/Deploy-Application-Archive.test.ps1 b/DeviceMigration/Archive/test/Deploy-Application-Archive.test.ps1 index bc03558..c1f0d78 100644 --- a/DeviceMigration/Archive/test/Deploy-Application-Archive.test.ps1 +++ b/DeviceMigration/Archive/test/Deploy-Application-Archive.test.ps1 @@ -1,4 +1,4 @@ -# <# +# <# # .SYNOPSIS # This script performs the installation or uninstallation of an application(s). # # LICENSE # diff --git a/DeviceMigration/Archive/test/Execute-MigrationToolkit-Archived.test.ps1 b/DeviceMigration/Archive/test/Execute-MigrationToolkit-Archived.test.ps1 index 516d9b7..9fabc84 100644 --- a/DeviceMigration/Archive/test/Execute-MigrationToolkit-Archived.test.ps1 +++ b/DeviceMigration/Archive/test/Execute-MigrationToolkit-Archived.test.ps1 @@ -1,4 +1,4 @@ -function Execute-MigrationToolkit { +function Execute-MigrationToolkit { <# .SYNOPSIS Executes the Migration Toolkit. diff --git a/DeviceMigration/Archive/test2/CreateODSyncUtil.Task.test.ps1 b/DeviceMigration/Archive/test2/CreateODSyncUtil.Task.test.ps1 index f71a88d..da18a75 100644 --- a/DeviceMigration/Archive/test2/CreateODSyncUtil.Task.test.ps1 +++ b/DeviceMigration/Archive/test2/CreateODSyncUtil.Task.test.ps1 @@ -59,7 +59,7 @@ Invoke-ModuleStarter @moduleStarterParams # TaskPrincipalGroupId = "BUILTIN\Users" # Specify the user group under which the task will run. # # Use this if you want the task to run under a specific group (e.g., "Administrators" or "Users"). -# # Leave this as is if you don’t need to specify a custom group and are using UseCurrentUser. +# # Leave this as is if you don[U+2019]t need to specify a custom group and are using UseCurrentUser. # ### VBS Hidden Execution (Optional) ### # HideWithVBS = $true # Set to `$true` if you want the task to run using a hidden VBScript (prevents a visible PowerShell window). @@ -170,7 +170,7 @@ $NewScheduledTaskUtilityTaskParams = @{ TaskPrincipalGroupId = "BUILTIN\Users" # Specify the user group under which the task will run. # Use this if you want the task to run under a specific group (e.g., "Administrators" or "Users"). - # Leave this as is if you don’t need to specify a custom group and are using UseCurrentUser. + # Leave this as is if you don[U+2019]t need to specify a custom group and are using UseCurrentUser. ### VBS Hidden Execution (Optional) ### HideWithVBS = $true # Set to `$true` if you want the task to run using a hidden VBScript (prevents a visible PowerShell window). diff --git a/DeviceMigration/Archive/test2/Deploy-Application.test.ps1 b/DeviceMigration/Archive/test2/Deploy-Application.test.ps1 index 9f392e3..28d50cf 100644 --- a/DeviceMigration/Archive/test2/Deploy-Application.test.ps1 +++ b/DeviceMigration/Archive/test2/Deploy-Application.test.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS PSApppDeployToolkit - This script performs the installation or uninstallation of an application(s). diff --git a/DeviceMigration/Files/ODSyncUtil/Get-ODStatusFromDLL.ps1 b/DeviceMigration/Files/ODSyncUtil/Get-ODStatusFromDLL.ps1 index b2c6d5c..275cd83 100644 --- a/DeviceMigration/Files/ODSyncUtil/Get-ODStatusFromDLL.ps1 +++ b/DeviceMigration/Files/ODSyncUtil/Get-ODStatusFromDLL.ps1 @@ -1,4 +1,4 @@ -<# +<# .Synopsis Get OneDrive Status .DESCRIPTION diff --git a/DeviceMigration/PSADT-Customizations/Deploy-Application.ps1 b/DeviceMigration/PSADT-Customizations/Deploy-Application.ps1 index 1029ec3..d86cbf5 100644 --- a/DeviceMigration/PSADT-Customizations/Deploy-Application.ps1 +++ b/DeviceMigration/PSADT-Customizations/Deploy-Application.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS PSApppDeployToolkit - This script performs the installation or uninstallation of an application(s). diff --git a/DeviceMigration/PSADT-Customizations/Deploy-Application.test.ps1 b/DeviceMigration/PSADT-Customizations/Deploy-Application.test.ps1 index 4864583..ba8d1a5 100644 --- a/DeviceMigration/PSADT-Customizations/Deploy-Application.test.ps1 +++ b/DeviceMigration/PSADT-Customizations/Deploy-Application.test.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS PSApppDeployToolkit - This script performs the installation or uninstallation of an application(s). diff --git a/DeviceMigration/PSAppDeployToolkit/Examples/VLC/Deploy-Application.ps1 b/DeviceMigration/PSAppDeployToolkit/Examples/VLC/Deploy-Application.ps1 index 8442860..5f9f392 100644 --- a/DeviceMigration/PSAppDeployToolkit/Examples/VLC/Deploy-Application.ps1 +++ b/DeviceMigration/PSAppDeployToolkit/Examples/VLC/Deploy-Application.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS PSApppDeployToolkit - This script performs the installation or uninstallation of an application(s). diff --git a/DeviceMigration/PSAppDeployToolkit/Examples/WinSCP/Deploy-Application.ps1 b/DeviceMigration/PSAppDeployToolkit/Examples/WinSCP/Deploy-Application.ps1 index 8d82700..1ebf536 100644 --- a/DeviceMigration/PSAppDeployToolkit/Examples/WinSCP/Deploy-Application.ps1 +++ b/DeviceMigration/PSAppDeployToolkit/Examples/WinSCP/Deploy-Application.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS PSApppDeployToolkit - This script performs the installation or uninstallation of an application(s). diff --git a/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitExtensions.ps1 b/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitExtensions.ps1 index 3c1dd6e..90c1f3b 100644 --- a/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitExtensions.ps1 +++ b/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitExtensions.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS PSAppDeployToolkit - Provides the ability to extend and customise the toolkit by adding your own functions that can be re-used. diff --git a/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitHelp.ps1 b/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitHelp.ps1 index d5b8c51..598ca37 100644 --- a/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitHelp.ps1 +++ b/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitHelp.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS PSApppDeployToolkit - Displays a graphical console to browse the help for the App Deployment Toolkit functions. diff --git a/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitMain.ps1 b/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitMain.ps1 index 08dbbf6..441bcb0 100644 --- a/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitMain.ps1 +++ b/DeviceMigration/PSAppDeployToolkit/Toolkit/AppDeployToolkit/AppDeployToolkitMain.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS PSAppDeployToolkit - This script contains the PSADT core runtime and functions using by a Deploy-Application.ps1 script. diff --git a/DeviceMigration/PSAppDeployToolkit/Toolkit/Deploy-Application.ps1 b/DeviceMigration/PSAppDeployToolkit/Toolkit/Deploy-Application.ps1 index 1029ec3..d86cbf5 100644 --- a/DeviceMigration/PSAppDeployToolkit/Toolkit/Deploy-Application.ps1 +++ b/DeviceMigration/PSAppDeployToolkit/Toolkit/Deploy-Application.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS PSApppDeployToolkit - This script performs the installation or uninstallation of an application(s). diff --git a/DeviceMigration/PSAppDeployToolkit/Toolkit/Deploy-Application.test.ps1 b/DeviceMigration/PSAppDeployToolkit/Toolkit/Deploy-Application.test.ps1 index 4864583..ba8d1a5 100644 --- a/DeviceMigration/PSAppDeployToolkit/Toolkit/Deploy-Application.test.ps1 +++ b/DeviceMigration/PSAppDeployToolkit/Toolkit/Deploy-Application.test.ps1 @@ -1,4 +1,4 @@ -<# +<# .SYNOPSIS PSApppDeployToolkit - This script performs the installation or uninstallation of an application(s).