diff --git a/Make.bat b/Make.bat index 817d266f5f6..5560e2f0bcc 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 @@ -53,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" @@ -127,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 ) @@ -139,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 ) @@ -322,20 +325,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 "%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 - ) - ) 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 @@ -345,8 +334,16 @@ 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 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 @@ -377,7 +374,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 ) @@ -411,11 +408,64 @@ REM Main build sequence Ends ECHO ************************************************************ ECHO * Failed to verify signature of the installer ECHO ************************************************************ - PAUSE + EXIT /B 1 + ) + + EXIT /B 0 + + +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 sha256 /v %* + IF %ERRORLEVEL% NEQ 0 ( + ECHO. + ECHO ************************************************************ + ECHO * Failed to sign one or more files + ECHO ************************************************************ + EXIT /B 1 ) EXIT /B 0 +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 ^(PGADMIN_WINDOWS_CSC is not set^)... + EXIT /B 0 + ) + + ECHO Attempting to sign the pgAdmin, PostgreSQL and Kerberos components... + + 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 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 ( + FOR /F "delims=" %%f IN ('DIR /B "%BUILDROOT%\python\%%p" 2^>nul') DO SET "COMPONENTS=!COMPONENTS! "%BUILDROOT%\python\%%f"" + ) + IF "!COMPONENTS!" == "" ( + ECHO. + ECHO ************************************************************ + ECHO * No components were found to sign + ECHO ************************************************************ + ENDLOCAL + EXIT /B 1 + ) + CALL :SIGN_FILES !COMPONENTS! || EXIT /B 1 + ENDLOCAL + + EXIT /B 0 :USAGE ECHO Invalid command line options. diff --git a/pkg/win32/README.md b/pkg/win32/README.md index 5a2925176f3..b69be239894 100644 --- a/pkg/win32/README.md +++ b/pkg/win32/README.md @@ -158,16 +158,23 @@ 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 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 +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 +207,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 +221,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.