Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/certbot/certbot.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrien Ferrand <adferrand@users.noreply.github.com>2019-09-23 22:29:18 +0300
committerBrad Warren <bmw@users.noreply.github.com>2019-09-23 22:29:18 +0300
commite402993c34ecf342db83bc3f0d8b34ae0d1d127a (patch)
tree8697007d864add86477f8a3d3641910296c9648d /windows-installer
parent754c34c12043bbbe3ceb12fb5660f841d09e3690 (diff)
[Windows] Create a certbot renew scheduled task using the installer (#7371)
This PR implements the item "register a scheduled task for certificate renewal" from the list of requirements described in #7365. This PR adds required instructions in the NSIS installer for Certbot to create a task, named "Certbot Renew Task" in the Windows Scheduler. This task is run twice a day, to execute the command certbot renew and keep the certificates up-to-date. Uninstalling Certbot will also remove this scheduled task. * Implementation * Corrections * Update template.nsi * Improve scripts * Add a random delay of 12 hours * Synchronize template against default one in pynsist 2.4 * Clean config of scheduled task * Install only in AllUsers mode * Add comments * Remove the logic of single user install
Diffstat (limited to 'windows-installer')
-rw-r--r--windows-installer/construct.py12
-rw-r--r--windows-installer/renew-down.ps16
-rw-r--r--windows-installer/renew-up.ps115
-rw-r--r--windows-installer/template.nsi257
4 files changed, 287 insertions, 3 deletions
diff --git a/windows-installer/construct.py b/windows-installer/construct.py
index 15296d559..2427c0128 100644
--- a/windows-installer/construct.py
+++ b/windows-installer/construct.py
@@ -19,7 +19,7 @@ def main():
installer_cfg_path = _generate_pynsist_config(repo_path, build_path)
- _prepare_build_tools(venv_path, venv_python)
+ _prepare_build_tools(venv_path, venv_python, repo_path)
_compile_wheels(repo_path, build_path, venv_python)
_build_installer(installer_cfg_path, venv_path)
@@ -47,12 +47,12 @@ def _compile_wheels(repo_path, build_path, venv_python):
subprocess.check_call(command)
-def _prepare_build_tools(venv_path, venv_python):
+def _prepare_build_tools(venv_path, venv_python, repo_path):
print('Prepare build tools')
subprocess.check_call([sys.executable, '-m', 'venv', venv_path])
subprocess.check_call(['choco', 'upgrade', '-y', 'nsis'])
subprocess.check_call([venv_python, '-m', 'pip', 'install', '--upgrade', 'pip'])
- subprocess.check_call([venv_python, '-m', 'pip', 'install', 'wheel', 'pynsist'])
+ subprocess.check_call([venv_python, os.path.join(repo_path, 'tools', 'pip_install.py'), 'wheel', 'pynsist'])
def _copy_assets(build_path, repo_path):
@@ -62,6 +62,9 @@ def _copy_assets(build_path, repo_path):
os.makedirs(build_path)
shutil.copy(os.path.join(repo_path, 'windows-installer', 'certbot.ico'), build_path)
shutil.copy(os.path.join(repo_path, 'windows-installer', 'run.bat'), build_path)
+ shutil.copy(os.path.join(repo_path, 'windows-installer', 'template.nsi'), build_path)
+ shutil.copy(os.path.join(repo_path, 'windows-installer', 'renew-up.ps1'), build_path)
+ shutil.copy(os.path.join(repo_path, 'windows-installer', 'renew-down.ps1'), build_path)
def _generate_pynsist_config(repo_path, build_path):
@@ -83,6 +86,7 @@ target=$INSTDIR\\run.bat
[Build]
directory=nsis
+nsi_template=template.nsi
installer_name=certbot-{certbot_version}-installer-{installer_suffix}.exe
[Python]
@@ -92,6 +96,8 @@ bitness={python_bitness}
[Include]
local_wheels=wheels\\*.whl
files=run.bat
+ renew-up.ps1
+ renew-down.ps1
[Command certbot]
entry_point=certbot.main:main
diff --git a/windows-installer/renew-down.ps1 b/windows-installer/renew-down.ps1
new file mode 100644
index 000000000..60dc4d9e6
--- /dev/null
+++ b/windows-installer/renew-down.ps1
@@ -0,0 +1,6 @@
+$taskName = "Certbot Renew Task"
+
+$exists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName}
+if ($exists) {
+ Unregister-ScheduledTask -TaskName $taskName -Confirm:$false
+}
diff --git a/windows-installer/renew-up.ps1 b/windows-installer/renew-up.ps1
new file mode 100644
index 000000000..c6a5fd9ea
--- /dev/null
+++ b/windows-installer/renew-up.ps1
@@ -0,0 +1,15 @@
+function Get-ScriptDirectory { Split-Path $MyInvocation.ScriptName }
+$down = Join-Path (Get-ScriptDirectory) 'renew-down.ps1'
+& $down
+
+$taskName = "Certbot Renew Task"
+
+$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument '-NoProfile -WindowStyle Hidden -Command "certbot renew"'
+$delay = New-TimeSpan -Hours 12
+$triggerAM = New-ScheduledTaskTrigger -Daily -At 12am -RandomDelay $delay
+$triggerPM = New-ScheduledTaskTrigger -Daily -At 12pm -RandomDelay $delay
+# NB: For now scheduled task is set up under SYSTEM account because Certbot Installer installs Certbot for all users.
+# If in the future we allow the Installer to install Certbot for one specific user, the scheduled task will need to
+# switch to this user, since Certbot will be available only for him.
+$principal = New-ScheduledTaskPrincipal -UserId SYSTEM -LogonType ServiceAccount -RunLevel Highest
+Register-ScheduledTask -Action $action -Trigger $triggerAM,$triggerPM -TaskName $taskName -Description "Execute twice a day the 'certbot renew' command, to renew managed certificates if needed." -Principal $principal
diff --git a/windows-installer/template.nsi b/windows-installer/template.nsi
new file mode 100644
index 000000000..0f366c22a
--- /dev/null
+++ b/windows-installer/template.nsi
@@ -0,0 +1,257 @@
+; This NSIS template is based on the built-in one in pynsist 2.3.
+; Added lines are enclosed within "CERTBOT CUSTOM BEGIN/END" comments.
+; If pynsist is upgraded, this template must be updated if necessary using the new built-in one.
+; Original file can be found here: https://github.com/takluyver/pynsist/blob/2.4/nsist/pyapp.nsi
+
+!define PRODUCT_NAME "[[ib.appname]]"
+!define PRODUCT_VERSION "[[ib.version]]"
+!define PY_VERSION "[[ib.py_version]]"
+!define PY_MAJOR_VERSION "[[ib.py_major_version]]"
+!define BITNESS "[[ib.py_bitness]]"
+!define ARCH_TAG "[[arch_tag]]"
+!define INSTALLER_NAME "[[ib.installer_name]]"
+!define PRODUCT_ICON "[[icon]]"
+
+; Marker file to tell the uninstaller that it's a user installation
+!define USER_INSTALL_MARKER _user_install_marker
+
+SetCompressor lzma
+
+; CERTBOT CUSTOM BEGIN
+; Administrator privileges are required to insert a new task in Windows Scheduler.
+; Also comment out some options to disable ability to choose AllUsers/CurrentUser install mode.
+; As a result, installer run always with admin privileges (because of MULTIUSER_EXECUTIONLEVEL),
+; using the AllUsers installation mode by default (because of MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
+; not set), and this default behavior cannot be overridden (because of MULTIUSER_MUI not set).
+; See https://nsis.sourceforge.io/Docs/MultiUser/Readme.html
+!define MULTIUSER_EXECUTIONLEVEL Admin
+;!define MULTIUSER_EXECUTIONLEVEL Highest
+;!define MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
+;!define MULTIUSER_MUI
+;!define MULTIUSER_INSTALLMODE_COMMANDLINE
+; CERTBOT CUSTOM END
+!define MULTIUSER_INSTALLMODE_INSTDIR "[[ib.appname]]"
+[% if ib.py_bitness == 64 %]
+!define MULTIUSER_INSTALLMODE_FUNCTION correct_prog_files
+[% endif %]
+!include MultiUser.nsh
+
+[% block modernui %]
+; Modern UI installer stuff
+!include "MUI2.nsh"
+!define MUI_ABORTWARNING
+!define MUI_ICON "[[icon]]"
+!define MUI_UNICON "[[icon]]"
+
+; UI pages
+[% block ui_pages %]
+!insertmacro MUI_PAGE_WELCOME
+[% if license_file %]
+!insertmacro MUI_PAGE_LICENSE [[license_file]]
+[% endif %]
+; CERTBOT CUSTOM BEGIN
+; Disable the installation mode page (AllUsers/CurrentUser)
+;!insertmacro MULTIUSER_PAGE_INSTALLMODE
+; CERTBOT CUSTOM END
+!insertmacro MUI_PAGE_DIRECTORY
+!insertmacro MUI_PAGE_INSTFILES
+!insertmacro MUI_PAGE_FINISH
+[% endblock ui_pages %]
+!insertmacro MUI_LANGUAGE "English"
+[% endblock modernui %]
+
+Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
+OutFile "${INSTALLER_NAME}"
+ShowInstDetails show
+
+Section -SETTINGS
+ SetOutPath "$INSTDIR"
+ SetOverwrite ifnewer
+SectionEnd
+
+[% block sections %]
+
+Section "!${PRODUCT_NAME}" sec_app
+ SetRegView [[ib.py_bitness]]
+ SectionIn RO
+ File ${PRODUCT_ICON}
+ SetOutPath "$INSTDIR\pkgs"
+ File /r "pkgs\*.*"
+ SetOutPath "$INSTDIR"
+
+ ; Marker file for per-user install
+ StrCmp $MultiUser.InstallMode CurrentUser 0 +3
+ FileOpen $0 "$INSTDIR\${USER_INSTALL_MARKER}" w
+ FileClose $0
+ SetFileAttributes "$INSTDIR\${USER_INSTALL_MARKER}" HIDDEN
+
+ [% block install_files %]
+ ; Install files
+ [% for destination, group in grouped_files %]
+ SetOutPath "[[destination]]"
+ [% for file in group %]
+ File "[[ file ]]"
+ [% endfor %]
+ [% endfor %]
+
+ ; Install directories
+ [% for dir, destination in ib.install_dirs %]
+ SetOutPath "[[ pjoin(destination, dir) ]]"
+ File /r "[[dir]]\*.*"
+ [% endfor %]
+ [% endblock install_files %]
+
+ [% block install_shortcuts %]
+ ; Install shortcuts
+ ; The output path becomes the working directory for shortcuts
+ SetOutPath "%HOMEDRIVE%\%HOMEPATH%"
+ [% if single_shortcut %]
+ [% for scname, sc in ib.shortcuts.items() %]
+ CreateShortCut "$SMPROGRAMS\[[scname]].lnk" "[[sc['target'] ]]" \
+ '[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
+ [% endfor %]
+ [% else %]
+ [# Multiple shortcuts: create a directory for them #]
+ CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
+ [% for scname, sc in ib.shortcuts.items() %]
+ CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\[[scname]].lnk" "[[sc['target'] ]]" \
+ '[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
+ [% endfor %]
+ [% endif %]
+ SetOutPath "$INSTDIR"
+ [% endblock install_shortcuts %]
+
+ [% block install_commands %]
+ [% if has_commands %]
+ DetailPrint "Setting up command-line launchers..."
+ nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_assemble_launchers.py" [[ python ]] "$INSTDIR\bin"'
+
+ StrCmp $MultiUser.InstallMode CurrentUser 0 AddSysPathSystem
+ ; Add to PATH for current user
+ nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" add_user "$INSTDIR\bin"'
+ GoTo AddedSysPath
+ AddSysPathSystem:
+ ; Add to PATH for all users
+ nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" add "$INSTDIR\bin"'
+ AddedSysPath:
+ [% endif %]
+ [% endblock install_commands %]
+
+ ; Byte-compile Python files.
+ DetailPrint "Byte-compiling Python modules..."
+ nsExec::ExecToLog '[[ python ]] -m compileall -q "$INSTDIR\pkgs"'
+ WriteUninstaller $INSTDIR\uninstall.exe
+ ; Add ourselves to Add/remove programs
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
+ "DisplayName" "${PRODUCT_NAME}"
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
+ "UninstallString" '"$INSTDIR\uninstall.exe"'
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
+ "InstallLocation" "$INSTDIR"
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
+ "DisplayIcon" "$INSTDIR\${PRODUCT_ICON}"
+ [% if ib.publisher is not none %]
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
+ "Publisher" "[[ib.publisher]]"
+ [% endif %]
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
+ "DisplayVersion" "${PRODUCT_VERSION}"
+ WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
+ "NoModify" 1
+ WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
+ "NoRepair" 1
+
+ ; CERTBOT CUSTOM BEGIN
+ ; Execute ps script to create the certbot renew task
+ DetailPrint "Setting up certbot renew scheduled task"
+ nsExec::ExecToStack 'powershell -inputformat none -ExecutionPolicy RemoteSigned -File "$INSTDIR\renew-up.ps1"'
+ ; CERTBOT CUSTOM END
+
+ ; Check if we need to reboot
+ IfRebootFlag 0 noreboot
+ MessageBox MB_YESNO "A reboot is required to finish the installation. Do you wish to reboot now?" \
+ /SD IDNO IDNO noreboot
+ Reboot
+ noreboot:
+SectionEnd
+
+Section "Uninstall"
+ ; CERTBOT CUSTOM BEGIN
+ ; Execute ps script to remove the certbot renew task
+ nsExec::ExecToStack 'powershell -inputformat none -ExecutionPolicy RemoteSigned -File "$INSTDIR\renew-down.ps1"'
+ ; CERTBOT CUSTOM END
+
+ SetRegView [[ib.py_bitness]]
+ SetShellVarContext all
+ IfFileExists "$INSTDIR\${USER_INSTALL_MARKER}" 0 +3
+ SetShellVarContext current
+ Delete "$INSTDIR\${USER_INSTALL_MARKER}"
+
+ Delete $INSTDIR\uninstall.exe
+ Delete "$INSTDIR\${PRODUCT_ICON}"
+ RMDir /r "$INSTDIR\pkgs"
+
+ ; Remove ourselves from %PATH%
+ [% block uninstall_commands %]
+ [% if has_commands %]
+ nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" remove "$INSTDIR\bin"'
+ [% endif %]
+ [% endblock uninstall_commands %]
+
+ [% block uninstall_files %]
+ ; Uninstall files
+ [% for file, destination in ib.install_files %]
+ Delete "[[pjoin(destination, file)]]"
+ [% endfor %]
+ ; Uninstall directories
+ [% for dir, destination in ib.install_dirs %]
+ RMDir /r "[[pjoin(destination, dir)]]"
+ [% endfor %]
+ [% endblock uninstall_files %]
+
+ [% block uninstall_shortcuts %]
+ ; Uninstall shortcuts
+ [% if single_shortcut %]
+ [% for scname in ib.shortcuts %]
+ Delete "$SMPROGRAMS\[[scname]].lnk"
+ [% endfor %]
+ [% else %]
+ RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
+ [% endif %]
+ [% endblock uninstall_shortcuts %]
+ RMDir $INSTDIR
+ DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
+SectionEnd
+
+[% endblock sections %]
+
+; Functions
+
+Function .onMouseOverSection
+ ; Find which section the mouse is over, and set the corresponding description.
+ FindWindow $R0 "#32770" "" $HWNDPARENT
+ GetDlgItem $R0 $R0 1043 ; description item (must be added to the UI)
+
+ [% block mouseover_messages %]
+ StrCmp $0 ${sec_app} "" +2
+ SendMessage $R0 ${WM_SETTEXT} 0 "STR:${PRODUCT_NAME}"
+
+ [% endblock mouseover_messages %]
+FunctionEnd
+
+Function .onInit
+ !insertmacro MULTIUSER_INIT
+FunctionEnd
+
+Function un.onInit
+ !insertmacro MULTIUSER_UNINIT
+FunctionEnd
+
+[% if ib.py_bitness == 64 %]
+Function correct_prog_files
+ ; The multiuser machinery doesn't know about the different Program files
+ ; folder for 64-bit applications. Override the install dir it set.
+ StrCmp $MultiUser.InstallMode AllUsers 0 +2
+ StrCpy $INSTDIR "$PROGRAMFILES64\${MULTIUSER_INSTALLMODE_INSTDIR}"
+FunctionEnd
+[% endif %] \ No newline at end of file