From c1597333e185e1539b39b47faa471b93e2a2fcfe Mon Sep 17 00:00:00 2001 From: Dave Page Date: Thu, 27 Aug 2026 11:10:21 +0100 Subject: [PATCH 1/7] Sign the bundled PostgreSQL binaries in the Windows build The Windows installer, the uninstaller and pgAdmin4.exe have always been Authenticode signed, but the PostgreSQL utilities we build and ship in the runtime directory (psql.exe, pg_dump.exe, pg_dumpall.exe and pg_restore.exe, along with libpq and the OpenSSL, zlib and related support libraries) were not, which leaves users running application allow-listing under WDAC or AppLocker unable to write publisher rules for them, and tends to attract antivirus and endpoint detection false positives. Factor the signtool invocation out into a SIGN_FILE subroutine and use it for both pgAdmin4.exe and each of the staged PostgreSQL components. As a side effect this also fixes the error check around the pgAdmin4.exe signing, which previously read %ERRORLEVEL% inside a parenthesised block and so expanded it before signtool had run. Also drop a couple of stray characters from the end of the pg_dumpall.exe staging line. --- Make.bat | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/Make.bat b/Make.bat index 817d266f5f6..a3765323009 100644 --- a/Make.bat +++ b/Make.bat @@ -324,14 +324,7 @@ REM Main build sequence Ends IF NOT "%PGADMIN_WINDOWS_CSC%" == "" ( ECHO Attempting to sign the pgAdmin4.exe... - CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /sm /n "%PGADMIN_WINDOWS_CSC%" /tr http://timestamp.digicert.com /td sha256 /fd sha1 /v "%BUILDROOT%\runtime\pgAdmin4.exe" - IF %ERRORLEVEL% NEQ 0 ( - ECHO. - ECHO ************************************************************ - ECHO * Failed to sign the pgAdmin4.exe - ECHO ************************************************************ - PAUSE - ) + CALL :SIGN_FILE "%BUILDROOT%\runtime\pgAdmin4.exe" ) ELSE ( ECHO Skipping code signing ^(PGADMIN_WINDOWS_CSC is not set^)... ) @@ -346,10 +339,19 @@ REM Main build sequence Ends IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\libzstd.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\libzstd.dll" "%BUILDROOT%\runtime" > nul COPY "%PGADMIN_POSTGRES_DIR%\bin\zlib1.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1 COPY "%PGADMIN_POSTGRES_DIR%\bin\pg_dump.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 - COPY "%PGADMIN_POSTGRES_DIR%\bin\pg_dumpall.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1L% + COPY "%PGADMIN_POSTGRES_DIR%\bin\pg_dumpall.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 COPY "%PGADMIN_POSTGRES_DIR%\bin\pg_restore.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 COPY "%PGADMIN_POSTGRES_DIR%\bin\psql.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 + IF NOT "%PGADMIN_WINDOWS_CSC%" == "" ( + ECHO Attempting to sign the PostgreSQL components... + ) ELSE ( + ECHO Skipping code signing of the PostgreSQL components ^(PGADMIN_WINDOWS_CSC is not set^)... + ) + FOR %%p IN (libpq.dll libcrypto-*-x64.dll libssl-*-x64.dll libintl-*.dll libiconv-*.dll liblz4.dll libzstd.dll zlib1.dll pg_dump.exe pg_dumpall.exe pg_restore.exe psql.exe) DO ( + FOR /F "delims=" %%f IN ('DIR /B "%BUILDROOT%\runtime\%%p" 2^>nul') DO CALL :SIGN_FILE "%BUILDROOT%\runtime\%%f" + ) + ECHO Staging VC++ runtime... MKDIR "%BUILDROOT%\installer" || EXIT /B 1 COPY "%PGADMIN_VCREDIST_DIR%\%PGADMIN_VCREDIST_FILE%" "%BUILDROOT%\installer" > nul || EXIT /B 1 @@ -417,6 +419,20 @@ REM Main build sequence Ends EXIT /B 0 +:SIGN_FILE + IF "%PGADMIN_WINDOWS_CSC%" == "" EXIT /B 0 + + CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /sm /n "%PGADMIN_WINDOWS_CSC%" /tr http://timestamp.digicert.com /td sha256 /fd sha1 /v %1 + IF %ERRORLEVEL% NEQ 0 ( + ECHO. + ECHO ************************************************************ + ECHO * Failed to sign %~nx1 + ECHO ************************************************************ + PAUSE + ) + + EXIT /B 0 + :USAGE ECHO Invalid command line options. ECHO Usage: "Make.bat [clean]" From d2e26070e61d32b5060c6c7a4af1e166788e6149 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Thu, 27 Aug 2026 11:20:01 +0100 Subject: [PATCH 2/7] Use SHA-256 file digests, and sign in a single signtool invocation The file digest was left at SHA-1 when we moved to the Certum hardware token, at a point where the certificate in the machine store had no key provider link and signing was therefore limited to SHA-1. The buildfarm now repairs that link with certutil as part of provisioning the Windows host, so SHA-256 works, and the setup notes recommend it. Switch both the runtime and the installer signing over. Whilst here, collect the PostgreSQL components and sign them in one signtool invocation rather than one per file, since the token prompts for a PIN on the first signature of a session and there is little point in provoking a dozen more of them. --- Make.bat | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/Make.bat b/Make.bat index a3765323009..d288681ccde 100644 --- a/Make.bat +++ b/Make.bat @@ -324,7 +324,7 @@ REM Main build sequence Ends IF NOT "%PGADMIN_WINDOWS_CSC%" == "" ( ECHO Attempting to sign the pgAdmin4.exe... - CALL :SIGN_FILE "%BUILDROOT%\runtime\pgAdmin4.exe" + CALL :SIGN_FILES "%BUILDROOT%\runtime\pgAdmin4.exe" ) ELSE ( ECHO Skipping code signing ^(PGADMIN_WINDOWS_CSC is not set^)... ) @@ -343,14 +343,7 @@ REM Main build sequence Ends COPY "%PGADMIN_POSTGRES_DIR%\bin\pg_restore.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 COPY "%PGADMIN_POSTGRES_DIR%\bin\psql.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 - IF NOT "%PGADMIN_WINDOWS_CSC%" == "" ( - ECHO Attempting to sign the PostgreSQL components... - ) ELSE ( - ECHO Skipping code signing of the PostgreSQL components ^(PGADMIN_WINDOWS_CSC is not set^)... - ) - FOR %%p IN (libpq.dll libcrypto-*-x64.dll libssl-*-x64.dll libintl-*.dll libiconv-*.dll liblz4.dll libzstd.dll zlib1.dll pg_dump.exe pg_dumpall.exe pg_restore.exe psql.exe) DO ( - FOR /F "delims=" %%f IN ('DIR /B "%BUILDROOT%\runtime\%%p" 2^>nul') DO CALL :SIGN_FILE "%BUILDROOT%\runtime\%%f" - ) + CALL :SIGN_POSTGRES_COMPONENTS ECHO Staging VC++ runtime... MKDIR "%BUILDROOT%\installer" || EXIT /B 1 @@ -379,7 +372,7 @@ REM Main build sequence Ends ECHO Creating windows installer using INNO tool... IF NOT "%PGADMIN_WINDOWS_CSC%" == "" ( - CALL "%PGADMIN_INNOTOOL_DIR%\ISCC.exe" "%WD%\pkg\win32\installer.iss" "/SpgAdminSigntool=%PGADMIN_SIGNTOOL_DIR%\signtool.exe sign /sm /n $q%PGADMIN_WINDOWS_CSC%$q /tr http://timestamp.digicert.com /td sha256 /fd sha1 /v $f" || EXIT /B 1 + CALL "%PGADMIN_INNOTOOL_DIR%\ISCC.exe" "%WD%\pkg\win32\installer.iss" "/SpgAdminSigntool=%PGADMIN_SIGNTOOL_DIR%\signtool.exe sign /sm /n $q%PGADMIN_WINDOWS_CSC%$q /tr http://timestamp.digicert.com /td sha256 /fd sha256 /v $f" || EXIT /B 1 ) ELSE ( CALL "%PGADMIN_INNOTOOL_DIR%\ISCC.exe" "%WD%\pkg\win32\installer.iss" || EXIT /B 1 ) @@ -419,20 +412,52 @@ REM Main build sequence Ends EXIT /B 0 -:SIGN_FILE +REM Sign one or more files, passed as quoted arguments. Signing is done in a +REM single signtool invocation as the hardware token prompts for a PIN on the +REM first signature of a session. +:SIGN_FILES IF "%PGADMIN_WINDOWS_CSC%" == "" EXIT /B 0 - CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /sm /n "%PGADMIN_WINDOWS_CSC%" /tr http://timestamp.digicert.com /td sha256 /fd sha1 /v %1 + CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /sm /n "%PGADMIN_WINDOWS_CSC%" /tr http://timestamp.digicert.com /td sha256 /fd sha256 /v %* IF %ERRORLEVEL% NEQ 0 ( ECHO. ECHO ************************************************************ - ECHO * Failed to sign %~nx1 + ECHO * Failed to sign one or more files ECHO ************************************************************ PAUSE ) EXIT /B 0 +REM Sign the PostgreSQL utilities and libraries staged in the runtime +REM directory. The library names are matched as patterns as they include +REM version numbers, and some of them are optional. +:SIGN_POSTGRES_COMPONENTS + IF "%PGADMIN_WINDOWS_CSC%" == "" ( + ECHO Skipping code signing of the PostgreSQL components ^(PGADMIN_WINDOWS_CSC is not set^)... + EXIT /B 0 + ) + + ECHO Attempting to sign the PostgreSQL components... + + SETLOCAL EnableDelayedExpansion + SET "PG_COMPONENTS=" + FOR %%p IN (libpq.dll libcrypto-*-x64.dll libssl-*-x64.dll libintl-*.dll libiconv-*.dll liblz4.dll libzstd.dll zlib1.dll pg_dump.exe pg_dumpall.exe pg_restore.exe psql.exe) DO ( + FOR /F "delims=" %%f IN ('DIR /B "%BUILDROOT%\runtime\%%p" 2^>nul') DO SET "PG_COMPONENTS=!PG_COMPONENTS! "%BUILDROOT%\runtime\%%f"" + ) + IF "!PG_COMPONENTS!" == "" ( + ECHO. + ECHO ************************************************************ + ECHO * No PostgreSQL components were found to sign + ECHO ************************************************************ + ENDLOCAL + EXIT /B 1 + ) + CALL :SIGN_FILES !PG_COMPONENTS! + ENDLOCAL + + EXIT /B 0 + :USAGE ECHO Invalid command line options. ECHO Usage: "Make.bat [clean]" From 27f8c01728dce0b86e5da6c5c87e62535c14ba9f Mon Sep 17 00:00:00 2001 From: Dave Page Date: Thu, 27 Aug 2026 11:22:14 +0100 Subject: [PATCH 3/7] Fail the Windows build when signing or verification fails A signing or verification failure called PAUSE, which is reasonable when a developer is watching the build but hangs the Jenkins agent indefinitely, leaving the job to be killed by hand rather than reported as failed. Return a non-zero exit code instead, and propagate it through the call sites so that the build stops at the point of failure. --- Make.bat | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Make.bat b/Make.bat index d288681ccde..a0ef8c3c798 100644 --- a/Make.bat +++ b/Make.bat @@ -324,7 +324,7 @@ REM Main build sequence Ends IF NOT "%PGADMIN_WINDOWS_CSC%" == "" ( ECHO Attempting to sign the pgAdmin4.exe... - CALL :SIGN_FILES "%BUILDROOT%\runtime\pgAdmin4.exe" + CALL :SIGN_FILES "%BUILDROOT%\runtime\pgAdmin4.exe" || EXIT /B 1 ) ELSE ( ECHO Skipping code signing ^(PGADMIN_WINDOWS_CSC is not set^)... ) @@ -343,7 +343,7 @@ REM Main build sequence Ends COPY "%PGADMIN_POSTGRES_DIR%\bin\pg_restore.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 COPY "%PGADMIN_POSTGRES_DIR%\bin\psql.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 - CALL :SIGN_POSTGRES_COMPONENTS + CALL :SIGN_POSTGRES_COMPONENTS || EXIT /B 1 ECHO Staging VC++ runtime... MKDIR "%BUILDROOT%\installer" || EXIT /B 1 @@ -406,7 +406,7 @@ REM Main build sequence Ends ECHO ************************************************************ ECHO * Failed to verify signature of the installer ECHO ************************************************************ - PAUSE + EXIT /B 1 ) EXIT /B 0 @@ -424,7 +424,7 @@ REM first signature of a session. ECHO ************************************************************ ECHO * Failed to sign one or more files ECHO ************************************************************ - PAUSE + EXIT /B 1 ) EXIT /B 0 @@ -453,7 +453,7 @@ REM version numbers, and some of them are optional. ENDLOCAL EXIT /B 1 ) - CALL :SIGN_FILES !PG_COMPONENTS! + CALL :SIGN_FILES !PG_COMPONENTS! || EXIT /B 1 ENDLOCAL EXIT /B 0 From 84f9edcd5e5edabf1c9255de94d98d7a71be06af Mon Sep 17 00:00:00 2001 From: Dave Page Date: Thu, 27 Aug 2026 12:39:28 +0100 Subject: [PATCH 4/7] Also sign the Kerberos components The Kerberos utilities and libraries staged into the python directory come from the same winpgbuild project as the PostgreSQL binaries, so they are our builds too and there is no reason to treat them differently. The default in Make.bat still points at an MIT Kerberos installation, but the buildfarm sets PGADMIN_KRB5_DIR to the winpgbuild output. Rather than signing each group where it is staged, do the whole lot in one pass once everything is in place, which keeps it to a single signtool invocation, and so a single PIN prompt from the hardware token, for the entire build. The Electron, Python and VC++ runtime components are left alone, being third party binaries that we do not build. --- Make.bat | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/Make.bat b/Make.bat index a0ef8c3c798..cb0ac3e51a8 100644 --- a/Make.bat +++ b/Make.bat @@ -26,6 +26,7 @@ CALL :CLEAN || EXIT /B 1 CALL :CREATE_VIRTUAL_ENV || EXIT /B 1 CALL :CREATE_PYTHON_ENV || EXIT /B 1 CALL :CREATE_RUNTIME_ENV || EXIT /B 1 +CALL :SIGN_COMPONENTS || EXIT /B 1 CALL :GENERATE_SBOM || EXIT /B 1 CALL :CREATE_INSTALLER || EXIT /B 1 CALL :VERIFY_SIGNATURE || EXIT /B 1 @@ -322,13 +323,6 @@ REM Main build sequence Ends %TMPDIR%\rcedit-x64.exe "%BUILDROOT%\runtime\pgAdmin4.exe" --set-version-string "ProductName" "%APP_NAME%" %TMPDIR%\rcedit-x64.exe "%BUILDROOT%\runtime\pgAdmin4.exe" --set-product-version "%APP_VERSION%" - IF NOT "%PGADMIN_WINDOWS_CSC%" == "" ( - ECHO Attempting to sign the pgAdmin4.exe... - CALL :SIGN_FILES "%BUILDROOT%\runtime\pgAdmin4.exe" || EXIT /B 1 - ) ELSE ( - ECHO Skipping code signing ^(PGADMIN_WINDOWS_CSC is not set^)... - ) - ECHO Staging PostgreSQL components... COPY "%PGADMIN_POSTGRES_DIR%\bin\libpq.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1 COPY "%PGADMIN_POSTGRES_DIR%\bin\libcrypto-*-x64.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1 @@ -343,8 +337,6 @@ REM Main build sequence Ends COPY "%PGADMIN_POSTGRES_DIR%\bin\pg_restore.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 COPY "%PGADMIN_POSTGRES_DIR%\bin\psql.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 - CALL :SIGN_POSTGRES_COMPONENTS || EXIT /B 1 - ECHO Staging VC++ runtime... MKDIR "%BUILDROOT%\installer" || EXIT /B 1 COPY "%PGADMIN_VCREDIST_DIR%\%PGADMIN_VCREDIST_FILE%" "%BUILDROOT%\installer" > nul || EXIT /B 1 @@ -429,31 +421,38 @@ REM first signature of a session. EXIT /B 0 -REM Sign the PostgreSQL utilities and libraries staged in the runtime -REM directory. The library names are matched as patterns as they include -REM version numbers, and some of them are optional. -:SIGN_POSTGRES_COMPONENTS +REM Sign the components that we build ourselves: the runtime executable, and +REM the PostgreSQL and Kerberos utilities and libraries obtained from the +REM winpgbuild project. The Electron, Python and VC++ runtime components are +REM deliberately left alone, as they are third party binaries that we do not +REM build, and signing them would replace any signature of their own. Names +REM are matched as patterns as some of the libraries include version numbers, +REM and some of them are optional. +:SIGN_COMPONENTS IF "%PGADMIN_WINDOWS_CSC%" == "" ( - ECHO Skipping code signing of the PostgreSQL components ^(PGADMIN_WINDOWS_CSC is not set^)... + ECHO Skipping code signing ^(PGADMIN_WINDOWS_CSC is not set^)... EXIT /B 0 ) - ECHO Attempting to sign the PostgreSQL components... + ECHO Attempting to sign the pgAdmin, PostgreSQL and Kerberos components... SETLOCAL EnableDelayedExpansion - SET "PG_COMPONENTS=" - FOR %%p IN (libpq.dll libcrypto-*-x64.dll libssl-*-x64.dll libintl-*.dll libiconv-*.dll liblz4.dll libzstd.dll zlib1.dll pg_dump.exe pg_dumpall.exe pg_restore.exe psql.exe) DO ( - FOR /F "delims=" %%f IN ('DIR /B "%BUILDROOT%\runtime\%%p" 2^>nul') DO SET "PG_COMPONENTS=!PG_COMPONENTS! "%BUILDROOT%\runtime\%%f"" + SET "COMPONENTS=" + FOR %%p IN (pgAdmin4.exe libpq.dll libcrypto-*-x64.dll libssl-*-x64.dll libintl-*.dll libiconv-*.dll liblz4.dll libzstd.dll zlib1.dll pg_dump.exe pg_dumpall.exe pg_restore.exe psql.exe) DO ( + FOR /F "delims=" %%f IN ('DIR /B "%BUILDROOT%\runtime\%%p" 2^>nul') DO SET "COMPONENTS=!COMPONENTS! "%BUILDROOT%\runtime\%%f"" + ) + FOR %%p IN (kinit.exe krb5_64.dll comerr64.dll k5sprt64.dll gssapi64.dll) DO ( + FOR /F "delims=" %%f IN ('DIR /B "%BUILDROOT%\python\%%p" 2^>nul') DO SET "COMPONENTS=!COMPONENTS! "%BUILDROOT%\python\%%f"" ) - IF "!PG_COMPONENTS!" == "" ( + IF "!COMPONENTS!" == "" ( ECHO. ECHO ************************************************************ - ECHO * No PostgreSQL components were found to sign + ECHO * No components were found to sign ECHO ************************************************************ ENDLOCAL EXIT /B 1 ) - CALL :SIGN_FILES !PG_COMPONENTS! || EXIT /B 1 + CALL :SIGN_FILES !COMPONENTS! || EXIT /B 1 ENDLOCAL EXIT /B 0 From 42cbf56e546e50caf86e6291a391be28b0069885 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Thu, 27 Aug 2026 12:44:27 +0100 Subject: [PATCH 5/7] Document the Windows build as it is actually done The default paths for the PostgreSQL and Kerberos binaries pointed at an EDB PostgreSQL installation and an MIT Kerberos for Windows installation, neither of which is what we have used for some time: both come from the winpgbuild project, and the buildfarm points at C:\build64\postgresql and C:\build64\krb5 accordingly. Make those the defaults, and adjust the messages that suggest where to get the binaries from. The README told the reader to download the workflow artifacts and merge them into a single directory, which no longer matches the layout of the archives. Point at the releases instead, which are not discarded after ninety days and which unpack straight into the expected directories, and correct the example environment variables to suit. The signing instructions were also left behind by the move to the hardware token: the certificate is no longer picked up automatically, and the build signs nothing unless PGADMIN_WINDOWS_CSC names the certificate to use, so document that. --- Make.bat | 10 +++++---- pkg/win32/README.md | 51 ++++++++++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/Make.bat b/Make.bat index cb0ac3e51a8..41a873e5e22 100644 --- a/Make.bat +++ b/Make.bat @@ -54,8 +54,8 @@ REM Main build sequence Ends :SET_ENVIRONMENT ECHO Configuring the environment... IF "%PGADMIN_PYTHON_DIR%" == "" SET "PGADMIN_PYTHON_DIR=C:\Python314" - IF "%PGADMIN_KRB5_DIR%" == "" SET "PGADMIN_KRB5_DIR=C:\Program Files\MIT\Kerberos" - IF "%PGADMIN_POSTGRES_DIR%" == "" SET "PGADMIN_POSTGRES_DIR=C:\Program Files\PostgreSQL\17" + IF "%PGADMIN_KRB5_DIR%" == "" SET "PGADMIN_KRB5_DIR=C:\build64\krb5" + IF "%PGADMIN_POSTGRES_DIR%" == "" SET "PGADMIN_POSTGRES_DIR=C:\build64\postgresql" IF "%PGADMIN_INNOTOOL_DIR%" == "" SET "PGADMIN_INNOTOOL_DIR=C:\Program Files (x86)\Inno Setup 6" IF "%PGADMIN_VCREDIST_DIR%" == "" SET "PGADMIN_VCREDIST_DIR=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.40.33807" IF "%PGADMIN_VCREDIST_FILE%" == "" SET "PGADMIN_VCREDIST_FILE=vc_redist.x64.exe" @@ -128,7 +128,8 @@ REM Main build sequence Ends IF NOT EXIST "%PGADMIN_KRB5_DIR%" ( ECHO !PGADMIN_KRB5_DIR! does not exist. - ECHO Please install MIT Kerberos for Windows and set the PGADMIN_KRB5_DIR environment variable. + ECHO Please install MIT Kerberos for Windows, from the winpgbuild project or + ECHO elsewhere, and set the PGADMIN_KRB5_DIR environment variable. EXIT /B 1 ) @@ -140,7 +141,8 @@ REM Main build sequence Ends IF NOT EXIST "%PGADMIN_POSTGRES_DIR%" ( ECHO !PGADMIN_POSTGRES_DIR! does not exist. - ECHO Please install PostgreSQL and set the PGADMIN_POSTGRES_DIR environment variable. + ECHO Please install PostgreSQL, from the winpgbuild project or elsewhere, and + ECHO set the PGADMIN_POSTGRES_DIR environment variable. EXIT /B 1 ) diff --git a/pkg/win32/README.md b/pkg/win32/README.md index 5a2925176f3..6d2795783e1 100644 --- a/pkg/win32/README.md +++ b/pkg/win32/README.md @@ -158,16 +158,20 @@ takes some effort to setup. It is therefore recommended that you simply download a pre-built set of PostgreSQL binaries from the -[winpgbuild project](https://github.com/dpage/winpgbuild/actions/workflows/postgresql.yml). -Locate the binaries asset for the version of PostgreSQL you wish to use -in the most recent workflow run, and extract the contents to a suitable -directory such as `C:\Build64`. - -Repeat the process with the latest build of -[MIT Kerberos](https://github.com/dpage/winpgbuild/actions/workflows/krb5.yml), -merging the files into the same set of directories. This is required because -the PostgreSQL build doesn't include Kerberos (gssapi) support as it uses -native SSPI instead. +[winpgbuild project](https://github.com/dpage/winpgbuild/releases). Download the +`postgresql--latest.zip` asset for the version of PostgreSQL you wish +to use, along with `krb5-latest.zip`, and unpack both of them into `C:\build64`. +MIT Kerberos is built and packaged separately because the PostgreSQL build +doesn't include Kerberos (gssapi) support, as it uses native SSPI instead. + +That will leave you with `C:\build64\postgresql` and `C:\build64\krb5`, which are +the directories the build system looks in by default. The same binaries are also +published as artifacts of the +[PostgreSQL](https://github.com/dpage/winpgbuild/actions/workflows/postgresql.yml) +and +[MIT Kerberos](https://github.com/dpage/winpgbuild/actions/workflows/krb5.yml) +workflow runs, although those are only retained for ninety days, so the releases +are usually the easier option. ## Setting up a dev environment @@ -200,8 +204,9 @@ desktop runtime. 1. Set the required environment variables, either system-wide, or in a Visual Studio 2017 (or 2022 with PostgreSQL 17+) 64bit command prompt. Note that the -examples shown below are the defaults for the build system, so if they match -your requirements you don't need to set them. For PostgreSQL 16 and below: +PostgreSQL 17 and later examples shown below are the defaults for the build +system, so if they match your requirements you don't need to set them. For +PostgreSQL 16 and below: SET "PGADMIN_POSTGRES_DIR=C:\build64\pgsql" SET "PGADMIN_PYTHON_DIR=C:\Python314" @@ -213,20 +218,28 @@ your requirements you don't need to set them. For PostgreSQL 16 and below: For PostgreSQL 17 and later: - SET "PGADMIN_POSTGRES_DIR=C:\build64" + SET "PGADMIN_POSTGRES_DIR=C:\build64\postgresql" SET "PGADMIN_PYTHON_DIR=C:\Python314" - SET "PGADMIN_KRB5_DIR=C:\build64" + SET "PGADMIN_KRB5_DIR=C:\build64\krb5" SET "PGADMIN_INNOTOOL_DIR=C:\Program Files (x86)\Inno Setup 6" SET "PGADMIN_SIGNTOOL_DIR=C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64" SET "PGADMIN_VCREDIST_DIR=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.40.33807" SET "PGADMIN_VCREDIST_FILE=vc_redist.x64.exe" -2. Run: +2. If you have a code signing certificate and wish to use it, set +`PGADMIN_WINDOWS_CSC` to its subject name. The certificate must be present in +the machine certificate store, along with a working link to its private key: - make + SET "PGADMIN_WINDOWS_CSC=Your Certificate Subject Name" + + The executables and libraries that we build ourselves will then be signed, + as will the installer and the uninstaller. If the variable is left unset, + the build completes as normal without signing anything. - If you have a code signing certificate, this will automatically be used if - found in the Windows Certificate Store to sign the installer. + +3. Run: + + make -3. Find the completed installer in the dist/ subdirectory of your source tree. +4. Find the completed installer in the dist/ subdirectory of your source tree. From 8b60b02e383f23983d3e5e92ed006038587a7112 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Thu, 27 Aug 2026 12:47:38 +0100 Subject: [PATCH 6/7] Correct the README on why Kerberos is downloaded separately The claim that the PostgreSQL build has no gssapi support because it uses native SSPI instead is no longer true of the version we ship: winpgbuild enables gssapi from PostgreSQL 18, which is what the buildfarm builds against. It was never quite the reason either, since the real obstacle before 18 was that gssapi could not be enabled alongside OpenSSL on Windows. Kerberos is needed regardless, because we ship kinit and the Kerberos runtime for pgAdmin's own Kerberos authentication. --- pkg/win32/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/win32/README.md b/pkg/win32/README.md index 6d2795783e1..b69be239894 100644 --- a/pkg/win32/README.md +++ b/pkg/win32/README.md @@ -161,8 +161,11 @@ PostgreSQL binaries from the [winpgbuild project](https://github.com/dpage/winpgbuild/releases). Download the `postgresql--latest.zip` asset for the version of PostgreSQL you wish to use, along with `krb5-latest.zip`, and unpack both of them into `C:\build64`. -MIT Kerberos is built and packaged separately because the PostgreSQL build -doesn't include Kerberos (gssapi) support, as it uses native SSPI instead. +MIT Kerberos is packaged separately and is needed in addition to the PostgreSQL +binaries, as pgAdmin ships `kinit` and the Kerberos runtime libraries to support +Kerberos authentication of its own. Note that PostgreSQL 17 and earlier are +built without gssapi support on Windows, which cannot be enabled alongside +OpenSSL before PostgreSQL 18. That will leave you with `C:\build64\postgresql` and `C:\build64\krb5`, which are the directories the build system looks in by default. The same binaries are also From 7868795d62eef167a13bd21becdac8abc9e30900 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Thu, 27 Aug 2026 12:50:48 +0100 Subject: [PATCH 7/7] Ship the Kerberos libraries that libpq links against from PG18 on From PostgreSQL 18, winpgbuild enables gssapi, and libpq.dll gained a load-time import of gssapi64.dll, which in turn pulls in krb5_64.dll, comerr64.dll and k5sprt64.dll; krbcc64.dll and xpprof64.dll are loaded later as credential cache and profile plugins. None of them were copied into the runtime directory, so psql.exe and the pg_dump family there depend on libraries that are not beside them, and start only if the loader happens to find copies elsewhere on the path. The set we ship in the python directory, for pgAdmin's own Kerberos support, is neither complete for this purpose nor in a directory the loader would search. Copy them alongside libpq, guarded on their presence so that PostgreSQL 17 and earlier, which have no gssapi support, are unaffected, and sign them with the rest. --- Make.bat | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Make.bat b/Make.bat index 41a873e5e22..5560e2f0bcc 100644 --- a/Make.bat +++ b/Make.bat @@ -334,6 +334,14 @@ REM Main build sequence Ends IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\liblz4.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\liblz4.dll" "%BUILDROOT%\runtime" > nul IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\libzstd.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\libzstd.dll" "%BUILDROOT%\runtime" > nul COPY "%PGADMIN_POSTGRES_DIR%\bin\zlib1.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1 + REM From PostgreSQL 18, libpq is built with gssapi support and loads the + REM Kerberos libraries below. They are absent from earlier builds. + IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\gssapi64.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\gssapi64.dll" "%BUILDROOT%\runtime" > nul + IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\krb5_64.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\krb5_64.dll" "%BUILDROOT%\runtime" > nul + IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\comerr64.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\comerr64.dll" "%BUILDROOT%\runtime" > nul + IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\k5sprt64.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\k5sprt64.dll" "%BUILDROOT%\runtime" > nul + IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\krbcc64.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\krbcc64.dll" "%BUILDROOT%\runtime" > nul + IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\xpprof64.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\xpprof64.dll" "%BUILDROOT%\runtime" > nul COPY "%PGADMIN_POSTGRES_DIR%\bin\pg_dump.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 COPY "%PGADMIN_POSTGRES_DIR%\bin\pg_dumpall.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 COPY "%PGADMIN_POSTGRES_DIR%\bin\pg_restore.exe" "%BUILDROOT%\runtime" > nul || EXIT /B 1 @@ -440,7 +448,7 @@ REM and some of them are optional. SETLOCAL EnableDelayedExpansion SET "COMPONENTS=" - FOR %%p IN (pgAdmin4.exe libpq.dll libcrypto-*-x64.dll libssl-*-x64.dll libintl-*.dll libiconv-*.dll liblz4.dll libzstd.dll zlib1.dll pg_dump.exe pg_dumpall.exe pg_restore.exe psql.exe) DO ( + FOR %%p IN (pgAdmin4.exe libpq.dll libcrypto-*-x64.dll libssl-*-x64.dll libintl-*.dll libiconv-*.dll liblz4.dll libzstd.dll zlib1.dll gssapi64.dll krb5_64.dll comerr64.dll k5sprt64.dll krbcc64.dll xpprof64.dll pg_dump.exe pg_dumpall.exe pg_restore.exe psql.exe) DO ( FOR /F "delims=" %%f IN ('DIR /B "%BUILDROOT%\runtime\%%p" 2^>nul') DO SET "COMPONENTS=!COMPONENTS! "%BUILDROOT%\runtime\%%f"" ) FOR %%p IN (kinit.exe krb5_64.dll comerr64.dll k5sprt64.dll gssapi64.dll) DO (