diff options
46 files changed, 1530 insertions, 204 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index dc0735836..5d9500e92 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -14,6 +14,8 @@ env: GOPATH: &gopath "/var/tmp/go" GOCACHE: "${GOPATH}/cache" GOSRC: &gosrc "/var/tmp/go/src/github.com/containers/podman" + # Store the unaltered default location, for tasks that need it + CIRRUS_DEFAULT_WORK: ${CIRRUS_WORKING_DIR} CIRRUS_WORKING_DIR: *gosrc # The default is 'sh' if unspecified CIRRUS_SHELL: "/bin/bash" @@ -60,9 +62,10 @@ env: # Curl-command prefix for downloading task artifacts, simply add the # the url-encoded task name, artifact name, and path as a suffix. + ART_URL: https://api.cirrus-ci.com/v1/artifact/build/${CIRRUS_BUILD_ID} ARTCURL: >- curl --retry 5 --retry-delay 8 --fail --location -O - --url https://api.cirrus-ci.com/v1/artifact/build/${CIRRUS_BUILD_ID} + --url ${ART_URL} # Default timeout for each task @@ -1019,6 +1022,7 @@ success_task: - consistency_aarch64 - alt_build - osx_alt_build + - win_installer - docker-py_test - unit_test - apiv2_test @@ -1103,6 +1107,24 @@ artifacts_task: type: application/octet-stream +win_installer_task: + name: "Verify Win Installer Build" + alias: win_installer + depends_on: + - alt_build + windows_container: + image: cirrusci/windowsservercore:2019 + env: + PATH: "${PATH};C:\\ProgramData\\chocolatey\\bin" + CIRRUS_SHELL: powershell + CIRRUS_CLONE_DEPTH: 1 + # Fake version, we are only testing the installer functions, so version doesn't matter + WIN_INST_VER: 9.9.9 + CIRRUS_WORKING_DIR: "${CIRRUS_DEFAULT_WORK}" + install_script: '.\contrib\cirrus\win-installer-install.ps1' + main_script: '.\contrib\cirrus\win-installer-main.ps1' + + # When a new tag is pushed, confirm that the code and commits # meet criteria for an official release. release_task: diff --git a/.github/workflows/upload-win-installer.yml b/.github/workflows/upload-win-installer.yml new file mode 100644 index 000000000..125100a28 --- /dev/null +++ b/.github/workflows/upload-win-installer.yml @@ -0,0 +1,96 @@ +name: Upload Windows Installer + +on: + release: + types: [created, published, edited] + workflow_dispatch: + inputs: + version: + description: 'Release version to build and upload (e.g. "4.2.1")' + required: true +jobs: + build: + runs-on: windows-latest + env: + FETCH_BASE_URL: ${{ github.server_url }}/${{ github.repository }} + steps: + - name: Determine version + id: getversion + run: | + $version = "${{ inputs.version }}" + if ($version.Length -lt 1) { + $version = "${{ github.event.release.tag_name }}" + if ($version.Length -lt 1) { + Write-Host "Could not determine version!" + Exit 1 + } + } + Write-Output "::set-output name=version::$version" + - uses: actions/checkout@v3 + - name: Check + id: check + run: | + Push-Location contrib\win-installer + .\check.ps1 ${{steps.getversion.outputs.version}} + $code = $LASTEXITCODE + if ($code -eq 2) { + Write-Output "::set-output name=already-exists::true" + Pop-Location + Exit 0 + } + Write-Output "UPLOAD_ASSET_NAME=$env:UPLOAD_ASSET_NAME" | Out-File -FilePath $env:GITHUB_ENV -Append + Pop-Location + Exit $code + - name: Set up Go + uses: actions/setup-go@v3 + if: steps.check.outputs.already-exists != 'true' + with: + go-version: 1.18 + - name: Setup Signature Tooling + if: steps.Check.outputs.already-exists != 'true' + run: | + dotnet tool install --global AzureSignTool --version 3.0.0 + echo "CERT_NAME=${{secrets.AZ_CERT_NAME}}" | Out-File -FilePath $env:GITHUB_ENV -Append + echo "VAULT_ID=${{secrets.AZ_VAULT_ID}}" | Out-File -FilePath $env:GITHUB_ENV -Append + echo "APP_ID=${{secrets.AZ_APP_ID}}" | Out-File -FilePath $env:GITHUB_ENV -Append + echo "TENANT_ID=${{secrets.AZ_TENANT_ID}}" | Out-File -FilePath $env:GITHUB_ENV -Append + echo "CLIENT_SECRET=${{secrets.AZ_CLIENT_SECRET}}" | Out-File -FilePath $env:GITHUB_ENV -Append + - name: Build + id: build + if: steps.check.outputs.already-exists != 'true' + run: | + Push-Location contrib\win-installer + .\build.ps1 ${{steps.getversion.outputs.version}} prod + $code = $LASTEXITCODE + if ($code -eq 2) { + Write-Output "::set-output name=artifact-missing::true" + Pop-Location + Exit 0 + } + Pop-Location + Exit $code + - name: Upload + if: steps.check.outputs.already-exists != 'true' && steps.build.outputs.artifact-missing != 'true' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + Push-Location contrib\win-installer + $version = "${{ steps.getversion.outputs.version }}" + if ($version[0] -ne "v") { + $version = "v$version" + } + gh release upload $version $ENV:UPLOAD_ASSET_NAME + if ($LASTEXITCODE -ne 0) { + .\check.ps1 $version + if ($LASTEXITCODE -eq 2) { + Write-Host "Another job uploaded before us, skipping" + Pop-Location + Exit 0 + } + Pop-Location + Exit 1 + } + if (Test-Path -Path shasums) { + gh release upload --clobber $version shasums + } + Pop-Location @@ -690,6 +690,9 @@ podman-remote-release-%.zip: test/version/version ## Build podman-remote for %=$ else \ $(MAKE) $(GOPLAT) podman-remote; \ fi + if [[ "$(GOOS)" == "windows" ]]; then \ + $(MAKE) $(GOPLAT) TMPDIR="" win-sshproxy; \ + fi cp -r ./docs/build/remote/$(GOOS) "$(TMPDIR)/$(SUBDIR)/docs/" cp ./contrib/remote/containers.conf "$(TMPDIR)/$(SUBDIR)/" $(MAKE) $(GOPLAT) $(_DSTARGS) SELINUXOPT="" install.remote @@ -752,6 +755,8 @@ install.remote: install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(BINDIR) install ${SELINUXOPT} -m 755 $(SRCBINDIR)/podman$(BINSFX) \ $(DESTDIR)$(BINDIR)/podman$(BINSFX) + test "${GOOS}" != "windows" || \ + install -m 755 $(SRCBINDIR)/win-sshproxy.exe $(DESTDIR)$(BINDIR) test -z "${SELINUXOPT}" || \ chcon --verbose --reference=$(DESTDIR)$(BINDIR)/podman-remote \ bin/podman-remote diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md index 66cc74693..17590be97 100644 --- a/RELEASE_PROCESS.md +++ b/RELEASE_PROCESS.md @@ -244,18 +244,17 @@ spelled with complete minutiae. $ make podman-remote-release-darwin_amd64.zip \ podman-remote-release-darwin_arm64.zip \ podman-remote-release-windows_amd64.zip \ - podman.msi \ podman-remote-static $ mv podman-* bin/ $ cd bin/ $ tar -cvzf podman-remote-static.tar.gz podman-remote-static - $ sha256sum *.zip *.msi *.tar.gz > shasums + $ sha256sum *.zip *.tar.gz > shasums ``` 1. The `podman-vX.Y.Z.dmg` file is produced manually by someone in possession of a developer signing key. 1. In the directory where you downloaded the archives, run - `sha256sum *.tar.gz *.zip *.msi > shasums` to generate SHA sums. + `sha256sum *.tar.gz *.zip > shasums` to generate SHA sums. 1. Go to `https://github.com/containers/podman/releases/tag/vX.Y.Z` and press the "Edit Release" button. Change the name to the form `vX.Y.Z` 1. If this is a release candidate be certain to click the pre-release @@ -273,4 +272,34 @@ spelled with complete minutiae. * podman-vX.Y.Z.msi * podman-remote-static.tar.gz * shasums - 1. Save the release. + 1. Click the Publish button to make the release (or pre-release) + available. + 1. Check the "Actions" tab, after the publish you should see a job + automatically launch to build the windows installer (named after + the release). There may be more than one running due to the multiple + event states triggered, but this can be ignored, as any duplicates + will gracefully back-off. The job takes 5-6 minutes to complete. + 1. Confirm the podman-[version]-setup.exe file is now on the release + page. This might not be the case if you accidentally published the + release before uploading the binaries, as the job may look before + they are available. If that happens, you can either manually kick + off the job (see below), or just make a harmless edit to the + release (e.g. add an extra whitespace character somewhere). As + long as the body content is different in some way, a new run will + be triggered. + + ## Manually Triggering Windows Installer Build & Upload + + + ### *CLI Approach* + 1. Install the GitHub CLI (e.g. `sudo dnf install gh`) + 1. Run (replacing below version number to release version) + ``` + gh workflow run "Upload Windows Installer" -F version="4.2.0" + ``` + ### *GUI Approach* + 1. Go to the "Actions" tab + 1. On the left pick the "Update Windows Installer" category + 1. A blue box will appear above the job list with a right side drop + -down. Click the drop-down and specify the version number in the + dialog that appears diff --git a/cmd/podman-msihooks/main.go b/cmd/podman-msihooks/main.go new file mode 100644 index 000000000..903c91abb --- /dev/null +++ b/cmd/podman-msihooks/main.go @@ -0,0 +1,46 @@ +//go:build windows +// +build windows + +package main + +import ( + "C" + "syscall" + "unsafe" + + "github.com/containers/podman/v4/pkg/machine/wsl" +) + +const KernelWarning = "WSL Kernel installation did not complete successfully. " + + "Podman machine will attempt to install this at a later time. " + + "You can also manually complete the installation using the " + + "\"wsl --update\" command." + +//export CheckWSL +func CheckWSL(hInstall uint32) uint32 { + installed := wsl.IsWSLInstalled() + feature := wsl.IsWSLFeatureEnabled() + setMsiProperty(hInstall, "HAS_WSL", strBool(installed)) + setMsiProperty(hInstall, "HAS_WSLFEATURE", strBool(feature)) + + return 0 +} + +func setMsiProperty(hInstall uint32, name string, value string) { + nameW, _ := syscall.UTF16PtrFromString(name) + valueW, _ := syscall.UTF16PtrFromString(value) + + msi := syscall.NewLazyDLL("msi") + proc := msi.NewProc("MsiSetPropertyW") + _, _, _ = proc.Call(uintptr(hInstall), uintptr(unsafe.Pointer(nameW)), uintptr(unsafe.Pointer(valueW))) + +} +func strBool(val bool) string { + if val { + return "1" + } + + return "0" +} + +func main() {} diff --git a/cmd/podman-wslkerninst/event-hook.go b/cmd/podman-wslkerninst/event-hook.go new file mode 100644 index 000000000..a5c23e4cf --- /dev/null +++ b/cmd/podman-wslkerninst/event-hook.go @@ -0,0 +1,73 @@ +//go:build windows +// +build windows + +package main + +import ( + "bytes" + "fmt" + + "github.com/sirupsen/logrus" + "golang.org/x/sys/windows/svc/eventlog" +) + +// Logrus hook that delegates to windows event log +type EventLogHook struct { + events *eventlog.Log +} + +type LogFormat struct { + name string +} + +func (f *LogFormat) Format(entry *logrus.Entry) ([]byte, error) { + var b *bytes.Buffer + + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + + fmt.Fprintf(b, "[%-5s] %s: %s", entry.Level.String(), f.name, entry.Message) + + for key, value := range entry.Data { + fmt.Fprintf(b, " {%s = %s}", key, value) + } + + b.WriteByte('\n') + return b.Bytes(), nil +} + +func NewEventHook(events *eventlog.Log, name string) *EventLogHook { + logrus.SetFormatter(&LogFormat{name}) + return &EventLogHook{events} +} + +func (hook *EventLogHook) Fire(entry *logrus.Entry) error { + line, err := entry.String() + if err != nil { + return err + } + + switch entry.Level { + case logrus.PanicLevel: + return hook.events.Error(1002, line) + case logrus.FatalLevel: + return hook.events.Error(1001, line) + case logrus.ErrorLevel: + return hook.events.Error(1000, line) + case logrus.WarnLevel: + return hook.events.Warning(1000, line) + case logrus.InfoLevel: + return hook.events.Info(1000, line) + case logrus.DebugLevel, logrus.TraceLevel: + return hook.events.Info(1001, line) + default: + return nil + } +} + +func (hook *EventLogHook) Levels() []logrus.Level { + return logrus.AllLevels +} diff --git a/cmd/podman-wslkerninst/main.go b/cmd/podman-wslkerninst/main.go new file mode 100644 index 000000000..0485db13c --- /dev/null +++ b/cmd/podman-wslkerninst/main.go @@ -0,0 +1,103 @@ +//go:build windows +// +build windows + +package main + +import ( + "fmt" + "os" + "path" + "syscall" + "time" + "unsafe" + + "github.com/containers/podman/v4/pkg/machine/wsl" + "github.com/sirupsen/logrus" + "golang.org/x/sys/windows/svc/eventlog" +) + +const ( + MB_ICONWARNING = 0x00000030 + MB_OK = 0x00000000 + MB_DEFBUTTON1 = 0x00000000 +) + +const KernelWarning = "WSL Kernel installation did not complete successfully. " + + "Podman machine will attempt to install this at a later time. " + + "You can also manually complete the installation using the " + + "\"wsl --update\" command." + +func setupLogging(name string) (*eventlog.Log, error) { + // Reuse the Built-in .NET Runtime Source so that we do not + // have to provide a messaage table and modify the system + // event configuration + log, err := eventlog.Open(".NET Runtime") + if err != nil { + return nil, err + } + + logrus.AddHook(NewEventHook(log, name)) + logrus.SetLevel(logrus.InfoLevel) + + return log, nil +} + +func installWslKernel() error { + logrus.Info("Installing WSL Kernel update") + var ( + err error + ) + backoff := 500 * time.Millisecond + for i := 1; i < 6; i++ { + err = wsl.SilentExec("wsl", "--update") + if err == nil { + break + } + + // In case of unusual circumstances (e.g. race with installer actions) + // retry a few times + logrus.Warn("An error occurred attempting the WSL Kernel update, retrying...") + time.Sleep(backoff) + backoff *= 2 + } + + if err != nil { + err = fmt.Errorf("could not install WSL Kernel: %w", err) + } + + return err +} + +// Creates an "warn" style pop-up window +func warn(title string, caption string) int { + format := MB_ICONWARNING | MB_OK | MB_DEFBUTTON1 + + user32 := syscall.NewLazyDLL("user32.dll") + captionPtr, _ := syscall.UTF16PtrFromString(caption) + titlePtr, _ := syscall.UTF16PtrFromString(title) + ret, _, _ := user32.NewProc("MessageBoxW").Call( + uintptr(0), + uintptr(unsafe.Pointer(captionPtr)), + uintptr(unsafe.Pointer(titlePtr)), + uintptr(format)) + + return int(ret) +} + +func main() { + args := os.Args + setupLogging(path.Base(args[0])) + if wsl.IsWSLInstalled() { + // nothing to do + logrus.Info("WSL Kernel already installed") + return + } + + result := installWslKernel() + if result != nil { + logrus.Error(result.Error()) + _ = warn("Podman Setup", KernelWarning) + } + + logrus.Info("WSL Kernel update successful") +} diff --git a/cmd/podman/root.go b/cmd/podman/root.go index f45dc94b2..0261cd670 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -475,8 +475,8 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) { pFlags.StringVar(&logLevel, logLevelFlagName, logLevel, fmt.Sprintf("Log messages above specified level (%s)", strings.Join(common.LogLevels, ", "))) _ = rootCmd.RegisterFlagCompletionFunc(logLevelFlagName, common.AutocompleteLogLevel) - pFlags.BoolVar(&debug, "debug", false, "Docker compatibility, force setting of log-level") - _ = pFlags.MarkHidden("debug") + lFlags.BoolVarP(&debug, "debug", "D", false, "Docker compatibility, force setting of log-level") + _ = lFlags.MarkHidden("debug") // Only create these flags for ABI connections if !registry.IsRemote() { diff --git a/contrib/cirrus/win-installer-install.ps1 b/contrib/cirrus/win-installer-install.ps1 new file mode 100644 index 000000000..f3fc4508d --- /dev/null +++ b/contrib/cirrus/win-installer-install.ps1 @@ -0,0 +1,6 @@ +# Update service is required for dotnet 3.5 (dep of wix) +Set-Service -Name wuauserv -StartupType "Manual" +choco install -y wixtoolset mingw golang archiver +if ($LASTEXITCODE -ne 0) { + Exit 1 +} diff --git a/contrib/cirrus/win-installer-main.ps1 b/contrib/cirrus/win-installer-main.ps1 new file mode 100644 index 000000000..64a94ee63 --- /dev/null +++ b/contrib/cirrus/win-installer-main.ps1 @@ -0,0 +1,60 @@ + # Powershell doesn't exit after + function CheckExit { + if ($LASTEXITCODE -ne 0) { + Exit $LASTEXITCODE + } +} +function DownloadFile { + param( + [Parameter(Mandatory)] + [string]$url, + [Parameter(Mandatory)] + [string]$file, + [Int]$retries=5, + [Int]$delay=8 + ) + $ProgressPreference = 'SilentlyContinue'; + Write-Host "Downloading $url to $file" + For($i = 0;;) { + Try { + Invoke-WebRequest -UseBasicParsing -ErrorAction Stop -Uri $url -OutFile $file + Break + } Catch { + if (++$i -gt $retries) { + throw $_.Exception + } + Write-Host "Download failed - retrying:" $_.Exception.Response.StatusCode + Start-Sleep -Seconds $delay + } + } +} +# Drop global envs which have unix paths, defaults are fine +Remove-Item Env:\GOPATH +Remove-Item Env:\GOSRC +Remove-Item Env:\GOCACHE + +Set-Location contrib\win-installer + +# Download and extract alt_build win release zip +$url = "${ENV:ART_URL}/Windows Cross/repo/repo.tbz" +# Arc requires extension to be "tbz2" +DownloadFile "$url" "repo.tbz2" +arc unarchive repo.tbz2 .; CheckExit + +# Build Installer +.\build.ps1 $Env:WIN_INST_VER dev repo; CheckExit + +# Run the installer silently and WSL install option disabled (prevent reboots, wsl requirements) +# We need AllowOldWin=1 for server 2019 (cirrus image), can be dropped after server 2022 +$ret = Start-Process -Wait -PassThru ".\podman-${ENV:WIN_INST_VER}-dev-setup.exe" -ArgumentList "/install /quiet WSLCheckbox=0 AllowOldWin=1 /log inst.log" +if ($ret.ExitCode -ne 0) { + Write-Host "Install failed, dumping log" + Get-Content inst.log + Exit $ret.ExitCode +} +if (! ((Test-Path -Path "C:\Program Files\RedHat\Podman\podman.exe") -and ` + (Test-Path -Path "C:\Program Files\RedHat\Podman\win-sshproxy.exe"))) { + Write-Host "Expected podman.exe and win-sshproxy.exe, one or both not present after install" + Exit 1 +} +Write-Host "Installer verification successful!" diff --git a/contrib/win-installer/README.md b/contrib/win-installer/README.md new file mode 100644 index 000000000..9cd1d29a5 --- /dev/null +++ b/contrib/win-installer/README.md @@ -0,0 +1,28 @@ +# Windows Installer Build + +## Requirements + +1. Win 10+ +2. Golang +3. MingW +4. Dotnet SDK (if AzureSignTool) +5. AzureSignTool (optional) +6. WiX Toolset + +## Usage + +``` +.\build.ps1 <version> [prod|dev] [release_dir] +``` + +## One off build (-dev output (default), unsigned (default)) + +``` +.\build.ps1 4.2.0 +``` + +## Build with a pre-downloaded win release zip in my-download dir + +``` +.\build.ps1 4.2.0 dev my-download +``` diff --git a/contrib/win-installer/build-burn.bat b/contrib/win-installer/build-burn.bat new file mode 100644 index 000000000..637a4e744 --- /dev/null +++ b/contrib/win-installer/build-burn.bat @@ -0,0 +1,7 @@ +@if "%1" == "" ( + @echo "usage: build-burn.bat <version>" + @exit /b 1 +) + +candle -ext WixUIExtension -ext WixUtilExtension -ext WixBalExtension -arch x64 -dManSource="docs" -dVERSION="%1" burn.wxs || exit /b 1 +light -ext WixUIExtension -ext WixUtilExtension -ext WixBalExtension .\burn.wixobj -out podman-setup.exe || exit /b 1 diff --git a/contrib/win-installer/build-hooks.bat b/contrib/win-installer/build-hooks.bat new file mode 100644 index 000000000..d663f87b8 --- /dev/null +++ b/contrib/win-installer/build-hooks.bat @@ -0,0 +1,4 @@ +cd ../.. +go build -buildmode=c-shared -o contrib/win-installer/artifacts/podman-msihooks.dll ./cmd/podman-msihooks || exit /b 1 +go build -ldflags -H=windowsgui -o contrib/win-installer/artifacts/podman-wslkerninst.exe ./cmd/podman-wslkerninst || exit /b 1 +cd contrib/win-installer diff --git a/contrib/win-installer/build-msi.bat b/contrib/win-installer/build-msi.bat new file mode 100644 index 000000000..28a77734d --- /dev/null +++ b/contrib/win-installer/build-msi.bat @@ -0,0 +1,8 @@ +@if "%1" == "" ( + @echo "usage: build-msi.bat <version>" + @exit /b 1 +) + +heat dir docs -var var.ManSource -cg ManFiles -dr INSTALLDIR -gg -g1 -srd -out pages.wxs || exit /b 1 +candle -ext WixUIExtension -ext WixUtilExtension -ext .\artifacts\PanelSwWixExtension.dll -arch x64 -dManSource="docs" -dVERSION="%1" podman.wxs pages.wxs podman-ui.wxs welcome-install-dlg.wxs || exit /b 1 +light -ext WixUIExtension -ext WixUtilExtension -ext .\artifacts\PanelSwWixExtension.dll .\podman.wixobj .\pages.wixobj .\podman-ui.wixobj .\welcome-install-dlg.wixobj -out podman.msi || exit /b 1 diff --git a/contrib/win-installer/build.ps1 b/contrib/win-installer/build.ps1 new file mode 100644 index 000000000..ba1b97548 --- /dev/null +++ b/contrib/win-installer/build.ps1 @@ -0,0 +1,156 @@ +function ExitOnError() { + if ($LASTEXITCODE -ne 0) { + Exit 1 + } +} + +function FetchPanel() { + Remove-Item -Recurse -Force -Path fetch -ErrorAction SilentlyContinue | Out-Null + New-Item -Force -ItemType Directory fetch | Out-Null + Push-Location fetch + + $ProgressPreference = 'SilentlyContinue' + Invoke-WebRequest -UseBasicParsing -OutFile nuget.exe -ErrorAction Stop ` + -Uri https://dist.nuget.org/win-x86-commandline/latest/nuget.exe + + .\nuget.exe install PanelSwWixExtension + $code = $LASTEXITCODE + Pop-Location + if ($code -gt 0) { + Exit 1 + } + $loc = Get-ChildItem -Recurse -Path fetch -Name PanelSwWixExtension.dll + if (!$loc) { + Write-Host "Could not locate PanelSwWixExtension.dll" + Exit 1 + } + + Copy-Item -Path fetch/$loc -Destination artifacts/PanelSwWixExtension.dll -ErrorAction Stop +} + +function SignItem() { + param( + [Parameter(Mandatory)] + [string[]]$fileNames + ) + + foreach ($val in $ENV:APP_ID, $ENV:TENANT_ID, $ENV:CLIENT_SECRET, $ENV:CERT_NAME) { + if (!$val) { + Write-Host "Skipping signing (no config)" + Return + } + } + + CheckCommand AzureSignTool.exe "AzureSignTool" + + AzureSignTool.exe sign -du "https://github.com/containers/podman" ` + -kvu "https://$ENV:VAULT_ID.vault.azure.net" ` + -kvi $ENV:APP_ID ` + -kvt $ENV:TENANT_ID ` + -kvs $ENV:CLIENT_SECRET ` + -kvc $ENV:CERT_NAME ` + -tr http://timestamp.digicert.com $fileNames + + ExitOnError +} + +function CheckCommand() { + param( + [Parameter(Mandatory)] + [string] $cmd, + [Parameter(Mandatory)] + [string] $description + ) + + if (! (Get-Command $cmd -errorAction SilentlyContinue)) { + Write-Host "Required dep `"$description`" is not installed" + Exit 1 + } +} + +function CheckRequirements() { + CheckCommand "gcc" "MingW CC" + CheckCommand "candle" "WiX Toolset" + CheckCommand "go" "Golang" +} + + +if ($args.Count -lt 1 -or $args[0].Length -lt 1) { + Write-Host "Usage: " $MyInvocation.MyCommand.Name "<version> [dev|prod] [release_dir]" + Write-Host + Write-Host 'Uses Env Vars: ' + Write-Host ' $ENV:FETCH_BASE_URL - GitHub Repo Address to locate release on' + Write-Host 'Env Settings for signing (optional)' + Write-Host ' $ENV:VAULT_ID' + Write-Host ' $ENV:APP_ID' + Write-Host ' $ENV:TENANT_ID' + Write-Host ' $ENV:CLIENT_SECRET' + Write-Host ' $ENV:CERT_NAME' + Write-Host + Write-Host "Example: Download and build from the official Github release (dev output): " + Write-Host " .\build.ps1 4.2.0" + Write-Host + Write-Host "Example: Build a dev build from a pre-download release " + Write-Host " .\build.ps1 4.2.0 dev fetchdir" + Write-Host + + Exit 1 +} + +# Pre-set to standard locations in-case build env does not refresh paths +$Env:Path="$Env:Path;C:\Program Files (x86)\WiX Toolset v3.11\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin;;C:\Program Files\Go\bin" + +CheckRequirements + +$version = $args[0] + +if ($version[0] -eq "v") { + $version = $version.Substring(1) +} + +$suffix = "-dev" +if ($args.Count -gt 1 -and $args[1] -eq "prod") { + $suffix = "" +} + +$releaseDir = "" +if ($args.Count -gt 2) { + $releaseDir = $args[2] +} + +.\process-release.ps1 $version $releaseDir +if ($LASTEXITCODE -eq 2) { + Write-Host "Skip signaled, relaying skip" + Exit 2 +} +if ($ENV:INSTVER -eq "") { + Write-Host "process-release did not define an install version!" + Exit 1 +} + +FetchPanel + +.\build-hooks.bat; ExitOnError +SignItem @("artifacts/win-sshproxy.exe", + "artifacts/podman.exe", + "artifacts/podman-msihooks.dll", + "artifacts/podman-wslkerninst.exe") + +.\build-msi.bat $ENV:INSTVER; ExitOnError +SignItem @("podman.msi") + +.\build-burn.bat $ENV:INSTVER; ExitOnError +insignia -ib podman-setup.exe -o engine.exe; ExitOnError +SignItem @("engine.exe") + +$file = "podman-$version$suffix-setup.exe" +insignia -ab engine.exe podman-setup.exe -o $file; ExitOnError +SignItem @("$file") + +if (Test-Path -Path shasums) { + $hash = (Get-FileHash -Algorithm SHA256 $file).Hash.ToLower() + Write-Output "$hash $file" | Out-File -Append -FilePath shasums +} + +Write-Host "Complete" +Get-ChildItem "podman-$version$suffix-setup.exe" diff --git a/contrib/win-installer/burn.wxs b/contrib/win-installer/burn.wxs new file mode 100644 index 000000000..f4534e5fd --- /dev/null +++ b/contrib/win-installer/burn.wxs @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"> + <?ifndef var.VERSION?> + <?error VERSION must be defined via command line argument?> + <?endif?> + <Bundle Name="Podman" Version="$(var.VERSION)" Manufacturer="Red Hat" + UpgradeCode="f3e1f40a-a791-49b7-9bc6-050975293353" IconSourceFile="resources\podman-logo.ico" + Compressed="yes"> + <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkSidebarLicense"> + <bal:WixStandardBootstrapperApplication LicenseUrl="" + ThemeFile="podman-theme.xml" + LocalizationFile="podman-theme.wxl" + LogoFile="resources\podman-banner2.png" + LogoSideFile="resources\podman-sidebar.png" + SuppressOptionsUI="yes" + ShowVersion="yes"/> + </BootstrapperApplicationRef> + <Variable Name='InstallFolder' Type='string' Value='[ProgramFiles64Folder]RedHat\Podman'/> + <Variable Name="VERSION" Value="$(var.VERSION)"/> + <Variable Name="WSLCheckbox" Type="numeric" Value="1" bal:Overridable="yes"/> + <Variable Name="AllowOldWin" Type="numeric" Value="0" bal:Overridable="yes"/> + <Variable Name="LaunchTarget" Value="explorer.exe"/> + <Variable Name="LaunchArguments" Value=""[InstallFolder]\podman-for-windows.html""/> + + <util:RegistrySearch Id="PreviousVersionSearch" Variable="PreviousVersion" Result="value" Root="HKLM" Key="SOFTWARE\[WixBundleManufacturer]\Updates\[WixBundleName]" Value="PackageVersion"/> + <util:RegistrySearch Id="PreviousInstallFolderSearch" Root="HKLM" Key="SOFTWARE\[WixBundleManufacturer]\[WixBundleName]" Value="InstallDir" Variable="PreviousInstallFolder"/> + <util:RegistrySearch Id="CurrentBuild" Variable="CBNumber" Result="value" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Value="CurrentBuildNumber"/> + <bal:Condition Message="Windows 10 (19041) or later is required to run this application."> + <![CDATA[VersionNT >= v10.0 AND (CBNumber >= 19041 OR AllowOldWin = 1)]]> + </bal:Condition> + <bal:Condition Message="You have an installed development, pre-release version, or alternative build identifying as the same version of this installer. You must uninstall the existing version of Podman first, before proceeding."> + <![CDATA[WixBundleAction <> 5 OR WixBundleInstalled OR WixBundleForcedRestartPackage OR PreviousVersion <> VERSION]]> + </bal:Condition> + <Chain> + <MsiPackage Id="Setup" SourceFile="podman.msi" Vital="yes"> + <MsiProperty Name="INSTALLDIR" Value="[InstallFolder]" /> + <MsiProperty Name="WITH_WSL" Value="[WSLCheckbox]"/> + </MsiPackage> + <ExePackage DisplayName="WSL Kernel Install" InstallCondition="WSLCheckbox = 1" SourceFile="artifacts\podman-wslkerninst.exe"/> + </Chain> + <OptionalUpdateRegistration/> + </Bundle> +</Wix> diff --git a/contrib/win-installer/check.ps1 b/contrib/win-installer/check.ps1 new file mode 100644 index 000000000..6e3aa9c2e --- /dev/null +++ b/contrib/win-installer/check.ps1 @@ -0,0 +1,63 @@ +function SkipExists { + param( + [Parameter(Mandatory)] + [string]$url, + [Parameter(Mandatory)] + [string]$desc + ) + try { + Invoke-WebRequest -Method HEAD -UseBasicParsing -ErrorAction Stop -Uri $url + Write-Host "$desc already uploaded, skipping..." + Exit 2 + } Catch { + if ($_.Exception.Response.StatusCode -eq 404) { + Write-Host "$desc does not exist, continuing..." + Return + } + + throw $_.Exception + } +} + +function SkipNotExists { + param( + [Parameter(Mandatory)] + [string]$url, + [Parameter(Mandatory)] + [string]$desc + ) + $ret = "" + try { + Invoke-WebRequest -Method HEAD -UseBasicParsing -ErrorAction Stop -Uri $url + Write-Host "$desc exists, continuing..." + } Catch { + if ($_.Exception.Response.StatusCode -eq 404) { + Write-Host "$desc does not exist, skipping ..." + Exit 2 + } + + throw $_.Exception + } +} + +if ($args.Count -lt 1 -or $args[0].Length -lt 2) { + Write-Host "Usage: " $MyInvocation.MyCommand.Name "<version>" + Exit 1 +} + +$release = $args[0] +$version = $release +if ($release[0] -eq "v") { + $version = $release.Substring(1) +} else { + $release = "v$release" +} + +$base_url = "$ENV:FETCH_BASE_URL" +if ($base_url.Length -le 0) { + $base_url = "https://github.com/containers/podman" +} + +$ENV:UPLOAD_ASSET_NAME = "podman-$version-setup.exe" +SkipExists "$base_url/releases/download/$release/podman-$version-setup.exe" "Installer" +SkipNotExists "$base_url/releases/download/$release/podman-remote-release-windows_amd64.zip" "Windows client zip" diff --git a/contrib/win-installer/podman-theme.wxl b/contrib/win-installer/podman-theme.wxl new file mode 100644 index 000000000..7fea09054 --- /dev/null +++ b/contrib/win-installer/podman-theme.wxl @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. --> + + +<WixLocalization Culture="en-us" Language="1033" xmlns="http://schemas.microsoft.com/wix/2006/localization"> + <String Id="Caption">[WixBundleName] [VERSION] Setup</String> + <String Id="Title">[WixBundleName] [VERSION]</String> + <String Id="InstallHeader">Welcome to [WixBundleName] Setup</String> + <String Id="InstallMessage">Welcome to the [WixBundleName] [VERSION] setup wizard. This will install [WixBundleName] on your computer. + +Additionally, you have the option to also install WSL (required by podman) if it is not already enabled. This operation requires a reboot during the installation process. Alternatively, you can deselect the WSL checkbox, and install WSL manually using the wsl --install command. + +Finally, click install to continue, or Close to abort the installation.</String> + <String Id="InstallVersion">Version [WixBundleVersion]</String> + <String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String> + <String Id="ExecuteUpgradeRelatedBundleMessage">Previous version</String> + <String Id="HelpHeader">Setup Help</String> + <String Id="HelpText">/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or + creates a complete local copy of the bundle in directory. Install is the default. + +/passive | /quiet - displays minimal UI with no prompts or displays no UI and + no prompts. By default UI and all prompts are displayed. + +/norestart - suppress any attempts to restart. By default UI will prompt before restart. +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.</String> + <String Id="HelpCloseButton">&Close</String> + <String Id="InstallLicenseLinkText">[WixBundleName] <a href="#">license terms</a>.</String> + <String Id="InstallAcceptCheckbox">I &agree to the license terms and conditions</String> + <String Id="InstallOptionsButton">&Options</String> + <String Id="InstallInstallButton">&Install</String> + <String Id="InstallCloseButton">&Close</String> + <String Id="OptionsHeader">Setup Options</String> + <String Id="OptionsLocationLabel">Install location:</String> + <String Id="OptionsBrowseButton">&Browse</String> + <String Id="OptionsOkButton">&OK</String> + <String Id="OptionsCancelButton">&Cancel</String> + <String Id="ProgressHeader">Setup Progress</String> + <String Id="ProgressLabel">Processing:</String> + <String Id="OverallProgressPackageText">Initializing...</String> + <String Id="ProgressCancelButton">&Cancel</String> + <String Id="ModifyHeader">Modify Setup</String> + <String Id="ModifyRepairButton">&Repair</String> + <String Id="ModifyUninstallButton">&Uninstall</String> + <String Id="ModifyCloseButton">&Close</String> + <String Id="SuccessRepairHeader">Repair Successfully Completed</String> + <String Id="SuccessUninstallHeader">Uninstall Successfully Completed</String> + <String Id="SuccessInstallHeader">Installation Successfully Completed</String> + <String Id="SuccessHeader">Setup Successful</String> + <String Id="SuccessLaunchButton">&Open Guide && Close</String> + <String Id="SuccessRestartText">You must restart your computer before you can use the software.</String> + <String Id="SuccessRestartButton">&Restart</String> + <String Id="SuccessCloseButton">&Close</String> + <String Id="FailureHeader">Setup Failed</String> + <String Id="FailureInstallHeader">Setup Failed</String> + <String Id="FailureUninstallHeader">Uninstall Failed</String> + <String Id="FailureRepairHeader">Repair Failed</String> + <String Id="FailureHyperlinkLogText">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>.</String> + <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String> + <String Id="FailureRestartButton">&Restart</String> + <String Id="FailureCloseButton">&Close</String> + <String Id="FilesInUseHeader">Files In Use</String> + <String Id="FilesInUseLabel">The following applications are using files that need to be updated:</String> + <String Id="FilesInUseCloseRadioButton">Close the &applications and attempt to restart them.</String> + <String Id="FilesInUseDontCloseRadioButton">&Do not close applications. A reboot will be required.</String> + <String Id="FilesInUseOkButton">&OK</String> + <String Id="FilesInUseCancelButton">&Cancel</String> + <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> +</WixLocalization> diff --git a/contrib/win-installer/podman-theme.xml b/contrib/win-installer/podman-theme.xml new file mode 100644 index 000000000..8d7be5d72 --- /dev/null +++ b/contrib/win-installer/podman-theme.xml @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. --> + + +<Theme xmlns="http://wixtoolset.org/schemas/thmutil/2010"> + <Window Width="600" Height="450" HexStyle="100a0000" FontId="0">#(loc.Title) Setup</Window> + <Font Id="0" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font> + <Font Id="1" Height="-24" Weight="500" Foreground="000000">Segoe UI</Font> + <Font Id="2" Height="-22" Weight="500" Foreground="666666">Segoe UI</Font> + <Font Id="3" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font> + <Font Id="4" Height="-12" Weight="500" Foreground="ff0000" Background="FFFFFF" Underline="yes">Segoe UI</Font> + <Font Id="5" Height="-28" Weight="500" Foreground="666666">Segoe UI</Font> + <Font Id="6" Height="-12" Weight="600" Foreground="000000" Background="FFFFFF">Segoe UI</Font> + <!-- Divider --> + <Font Id="7" Height="-24" Weight="500" Foreground="000000" Background="E0E0E0">Segoe UI</Font> + <Text X="11" Y="-45" Width="-11" Height="2" FontId="7" Visible="yes"></Text> + <Page Name="Help"> + <Image X="11" Y="11" Width="206" Height="64" ImageFile="logo.png"/> + <Text X="11" Y="80" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Text> + <Text X="11" Y="121" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Text> + <Button Name="HelpCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.HelpCloseButton)</Button> + </Page> + <Page Name="Install"> + <Image X="11" Y="11" Width="165" Height="364" ImageFile="logoside.png"/> + <Text X="185" Y="11" Width="-11" Height="40" FontId="5" DisablePrefix="yes">#(loc.InstallHeader)</Text> + <Text X="185" Y="82" Width="-11" Height="160" FontId="3" DisablePrefix="yes">#(loc.InstallMessage)</Text><!-- HexStyle="0x800000" --> + + <Hypertext Name="EulaHyperlink" X="185" Y="-111" Width="-11" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallLicenseLinkText)</Hypertext> + <Text Name="InstallVersion" X="185" Y="-61" Width="-11" Height="17" FontId="3" DisablePrefix="yes" HideWhenDisabled="yes">#(loc.InstallVersion)</Text> + <Checkbox Name="WSLCheckbox" X="185" Y="250" Width="-11" Height="17" TabStop="yes" FontId="6" HideWhenDisabled="yes">Install WSL if not present</Checkbox> + <Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.InstallOptionsButton)</Button> + <Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button> + <Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button> + </Page> + <Page Name="Options"> + <Image X="11" Y="11" Width="206" Height="64" ImageFile="logo.png"/> + <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Text> + <Text X="11" Y="121" Width="-11" Height="17" FontId="3">#(loc.OptionsLocationLabel)</Text> + <Editbox Name="FolderEditbox" X="11" Y="143" Width="-91" Height="21" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" /> + <Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" TabStop="yes" FontId="3">#(loc.OptionsBrowseButton)</Button> + + <Button Name="OptionsOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.OptionsOkButton)</Button> + <Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.OptionsCancelButton)</Button> + </Page> + <Page Name="FilesInUse"> + <Image X="11" Y="11" Width="206" Height="64" ImageFile="logo.png"/> + <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.FilesInUseHeader)</Text> + <Text X="11" Y="121" Width="-11" Height="34" FontId="3" DisablePrefix="yes">#(loc.FilesInUseLabel)</Text> + <Text Name="FilesInUseText" X="11" Y="150" Width="-11" Height="-86" FontId="3" DisablePrefix="yes" HexStyle="0x0000000C"></Text> + + <Button Name="FilesInUseCloseRadioButton" X="11" Y="-70" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseCloseRadioButton)</Button> + <Button Name="FilesInUseDontCloseRadioButton" X="11" Y="-50" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseDontCloseRadioButton)</Button> + + <Button Name="FilesInUseOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FilesInUseOkButton)</Button> + <Button Name="FilesInUseCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FilesInUseCancelButton)</Button> + </Page> + <Page Name="Progress"> + <Image X="11" Y="11" Width="206" Height="64" ImageFile="logo.png"/> + <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Text> + <Text X="11" Y="141" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Text> + <Text Name="OverallProgressPackageText" X="85" Y="141" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Text> + <Progressbar Name="OverallCalculatedProgressbar" X="11" Y="163" Width="-11" Height="20" /> + <Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button> + </Page> + <Page Name="Modify"> + <Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text> + <Image X="11" Y="11" Width="165" Height="364" ImageFile="logoside.png"/> + <Text X="185" Y="50" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Text> + <Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button> + <Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button> + <Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyCloseButton)</Button> + </Page> + <Page Name="Success"> + <Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text> + <Image X="11" Y="11" Width="165" Height="364" ImageFile="logoside.png"/> + <Text Name="SuccessHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessHeader)</Text> + <Text Name="SuccessInstallHeader" X="185" Y="50" Width="-11" Height="100" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessInstallHeader)</Text> + <Text Name="SuccessRepairHeader" X="185" Y="50" Width="-11" Height="100" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRepairHeader)</Text> + <Text Name="SuccessUninstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessUninstallHeader)</Text> + <Button Name="LaunchButton" X="-91" Y="-11" Width="125" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button> + <Text Name="SuccessRestartText" X="185" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRestartText)</Text> + <Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button> + <Button Name="SuccessCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.SuccessCloseButton)</Button> + </Page> + <Page Name="Failure"> + <Image X="11" Y="11" Width="165" Height="364" ImageFile="logoside.png"/> + <Text Name="FailureHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureHeader)</Text> + <Text Name="FailureInstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureInstallHeader)</Text> + <Text Name="FailureUninstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureUninstallHeader)</Text> + <Text Name="FailureRepairHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRepairHeader)</Text> + <Hypertext Name="FailureLogFileLink" X="185" Y="121" Width="-11" Height="68" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext> + <Hypertext Name="FailureMessageText" X="185" Y="-115" Width="-11" Height="80" FontId="3" TabStop="yes" HideWhenDisabled="yes" /> + <Text Name="FailureRestartText" X="185" Y="-57" Width="-11" Height="80" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRestartText)</Text> + <Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button> + <Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FailureCloseButton)</Button> + </Page> +</Theme> diff --git a/contrib/win-installer/podman-ui.wxs b/contrib/win-installer/podman-ui.wxs new file mode 100644 index 000000000..127045950 --- /dev/null +++ b/contrib/win-installer/podman-ui.wxs @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. --> + +<!-- +First-time install dialog sequence: + - WixUI_WelcomeEulaDlg + +Maintenance dialog sequence: + WixUI_MaintenanceWelcomeDlg + - WixUI_MaintenanceTypeDlg + - WixUI_VerifyReadyDlg + +Patch dialog sequence: + - WixUI_WelcomeDlg + - WixUI_VerifyReadyDlg +--> + +<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> + <Fragment> + <UI Id="PodmanUI"> + <TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" /> + <TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" /> + <TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" /> + + <Property Id="DefaultUIFont" Value="WixUI_Font_Normal" /> + <Property Id="WixUI_Mode" Value="Minimal" /> + + <DialogRef Id="ErrorDlg" /> + <DialogRef Id="FatalError" /> + <DialogRef Id="FilesInUse" /> + <DialogRef Id="MsiRMFilesInUse" /> + <DialogRef Id="PrepareDlg" /> + <DialogRef Id="ProgressDlg" /> + <DialogRef Id="ResumeDlg" /> + <DialogRef Id="UserExit" /> + <DialogRef Id="WelcomeDlg" /> + <DialogRef Id="WelcomeInstallDlg" /> + + <Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish> + + <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish> + + <Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish> + + <Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish> + <Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish> + <Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish> + + <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish> + <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">Installed AND PATCH</Publish> + + <InstallUISequence> + <Show Dialog="WelcomeDlg" Before="WelcomeInstallDlg">Installed AND PATCH</Show> + <Show Dialog="WelcomeInstallDlg" Before="ProgressDlg">(NOT Installed) AND NOT AFTERREBOOT</Show> + </InstallUISequence> + + <Property Id="ARPNOMODIFY" Value="1" /> + </UI> + + <UIRef Id="WixUI_Common" /> + </Fragment> +</Wix> diff --git a/contrib/win-installer/podman.wxs b/contrib/win-installer/podman.wxs new file mode 100644 index 000000000..b61bb2802 --- /dev/null +++ b/contrib/win-installer/podman.wxs @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8"?> +<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" + xmlns:PanelSW="http://schemas.panel-sw.co.il/wix/WixExtension"> + + <?ifndef var.VERSION?> + <?error VERSION must be defined via command line argument?> + <?endif?> + + <Product Name="Podman $(var.VERSION)" Id="*" UpgradeCode="696BAB5D-CA1F-4B05-B123-320F245B8D6D" Version="$(var.VERSION)" Language="1033" Manufacturer="Red Hat Inc."> + + <Package Id="*" Platform="x64" Keywords="Installer" Description="Red Hat's Podman $(var.VERSION) Installer" Comments="Apache 2.0 License" Manufacturer="Red Hat Inc." InstallScope="perMachine" InstallerVersion="200" Compressed="yes"/> + + <Media Id="1" Cabinet="Podman.cab" EmbedCab="yes"/> + <MajorUpgrade AllowDowngrades="yes"/> + <Property Id="DiskPrompt" Value="Red Hat's Podman $(var.VERSION) Installation"/> + <SetProperty Id="WSL_INSTALL" Before="AppSearch" Value="1" Sequence="first">NOT (WITH_WSL = 0)</SetProperty> + <Directory Id="TARGETDIR" Name="SourceDir"> + <Directory Id="ProgramFiles64Folder" Name="PFiles"> + <Directory Id="RedHatPFiles" Name="RedHat"> + <Directory Id="INSTALLDIR" Name="Podman"> + <Component Id="INSTALLDIR_Component" Guid="14B310C4-9B5D-4DA5-ADF9-B9D008E4CD82" Win64="yes"> + <CreateFolder/> + </Component> + <Component Id="MainExecutable" Guid="73752F94-6589-4C7B-ABED-39D655A19714" Win64="yes"> + <File Id="MainExecutableFile" Name="podman.exe" Source="artifacts/podman.exe" KeyPath="yes"/> + </Component> + <Component Id="WinSshProxyExecutable" Guid="0DA730AB-2F97-40E8-A8FC-356E88EAA4D2" Win64="yes"> + <File Id="WinSshProxyExecutableFile" Name="win-sshproxy.exe" Source="artifacts/win-sshproxy.exe" KeyPath="yes"/> + </Component> + <Component Id="GuideHTMLComponent" Guid="8B23C76B-F7D4-4030-8C46-1B5729E616B5" Win64="yes"> + <File Id="GuideHTMLFile" Name="welcome-podman.html" Source="docs/podman-for-windows.html" KeyPath="yes"/> + </Component> + </Directory> + </Directory> + </Directory> + <Directory Id="EnvEntries"> + <Component Id="EnvEntriesComponent" Guid="b662ec43-0e0e-4018-8bf3-061904bb8f5b" Win64="yes"> + <CreateFolder /> + <Environment Id='UpdatePath' Name='PATH' Action='set' Permanent='no' System='yes' Part='last' Value='[INSTALLDIR]' /> + </Component> + </Directory> + </Directory> + + <CustomAction Id="OpenGuide" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" /> + <CustomAction Id="CheckWSL" BinaryKey="PodmanHooks" Execute="immediate" DllEntry="CheckWSL" /> + <CustomActionRef Id="WixBroadcastEnvironmentChange" /> + <ComponentGroup Id="WSLFeature" Directory="INSTALLDIR"> + <Component> + <Condition>(NOT Installed) AND WSL_INSTALL = 1 AND HAS_WSLFEATURE = 0</Condition> + <File Source="$(sys.SOURCEFILEPATH)"/> + <PanelSW:Dism EnableFeature="VirtualMachinePlatform" ErrorHandling="prompt"/> + <PanelSW:Dism EnableFeature="Microsoft-Windows-Subsystem-Linux" ErrorHandling="prompt"/> + </Component> + </ComponentGroup> + <Feature Id="Complete" Level="1"> + <ComponentRef Id="INSTALLDIR_Component"/> + <ComponentRef Id="EnvEntriesComponent"/> + <ComponentRef Id="MainExecutable"/> + <ComponentRef Id="WinSshProxyExecutable"/> + <ComponentRef Id="GuideHTMLComponent"/> + <ComponentGroupRef Id="ManFiles"/> + <ComponentGroupRef Id="WSLFeature"/> + </Feature> + + <Icon Id="podman.ico" SourceFile="resources/podman-logo.ico"/> + <Property Id="ARPPRODUCTICON" Value="podman.ico"/> + <Property Id="WixShellExecTarget" Value="[#GuideHTMLFile]" /> + <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Show Getting Started Guide" /> + <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" /> + <WixVariable Id="WixUIBannerBmp" Value="resources\podman-banner.png" /> + <WixVariable Id="WixUIDialogBmp" Value="resources\podman-dialog.png" /> + <UIRef Id="PodmanUI"/> + <UI> + <Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" + Value="OpenGuide">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish> + </UI> + + <InstallExecuteSequence> + <Custom Action="CheckWSL" After="SetWSL_INSTALL">WSL_INSTALL = 1</Custom> + <ForceReboot Before="StopServices">(NOT Installed) AND WSL_INSTALL = 1 AND HAS_WSLFEATURE = 0 AND NOT AFTERREBOOT</ForceReboot> + </InstallExecuteSequence> + <Binary Id="PodmanHooks" SourceFile="artifacts/podman-msihooks.dll" /> + </Product> +</Wix> diff --git a/contrib/win-installer/process-release.ps1 b/contrib/win-installer/process-release.ps1 new file mode 100644 index 000000000..ba7b47f4b --- /dev/null +++ b/contrib/win-installer/process-release.ps1 @@ -0,0 +1,158 @@ +function Copy-Artifact { + param( + [Parameter(Mandatory)] + [string]$fileName + ) + $file = Get-ChildItem -Recurse -Path . -Name $fileName + if (!$file) { + throw "Could not find $filename" + } + Write-Host "file:" $file + Copy-Item -Path $file -Destination "..\artifacts\$filename" -ErrorAction Stop +} + +function DownloadOrSkip { + param( + [Parameter(Mandatory)] + [string]$url, + [Parameter(Mandatory)] + [string]$file + ) + $ProgressPreference = 'SilentlyContinue'; + try { + Invoke-WebRequest -UseBasicParsing -ErrorAction Stop -Uri $url -OutFile $file + } Catch { + if ($_.Exception.Response.StatusCode -eq 404) { + Write-Host "URL not available, signaling skip:" + Write-Host "URL: $url" + Exit 2 + } + + throw $_.Exception + } +} + +function DownloadOptional { + param( + [Parameter(Mandatory)] + [string]$url, + [Parameter(Mandatory)] + [string]$file + ) + $ProgressPreference = 'SilentlyContinue'; + try { + Invoke-WebRequest -UseBasicParsing -ErrorAction Stop -Uri $url -OutFile $file + } Catch { + } + + Return +} + + +if ($args.Count -lt 1) { + Write-Host "Usage: " $MyInvocation.MyCommand.Name "<version> [release_dir]" + Exit 1 +} + +$releaseDir = "" +if ($args.Count -gt 1 -and $args[1].Length -gt 0) { + $path = $args[1] + $releaseDir = (Resolve-Path -Path "$path" -ErrorAction Stop).Path +} + + +$base_url = "$ENV:FETCH_BASE_URL" +if ($base_url.Length -le 0) { + $base_url = "https://github.com/containers/podman" +} + +$version = $args[0] +if ($version -notmatch '^v?([0-9]+\.[0-9]+\.[0-9]+)(-.*)?$') { + Write-Host "Invalid version" + Exit 1 +} + +# WiX burn requires a QWORD version only, numeric only +$Env:INSTVER=$Matches[1] + +if ($version[0] -ne 'v') { + $version = 'v' + $version +} + +$restore = 0 +$exitCode = 0 + +try { + Write-Host "Cleaning up old artifacts" + Remove-Item -Force -Recurse -Path .\docs -ErrorAction SilentlyContinue | Out-Null + Remove-Item -Force -Recurse -Path .\artifacts -ErrorAction SilentlyContinue | Out-Null + Remove-Item -Force -Recurse -Path .\fetch -ErrorAction SilentlyContinue | Out-Null + + New-Item fetch -ItemType Directory | Out-Null + New-Item artifacts -ItemType Directory | Out-Null + + Write-Host "Fetching zip release" + + Push-Location fetch -ErrorAction Stop + $restore = 1 + $ProgressPreference = 'SilentlyContinue'; + + if ($releaseDir.Length -gt 0) { + Copy-Item -Path "$releaseDir/podman-remote-release-windows_amd64.zip" "release.zip" + } else { + DownloadOrSkip "$base_url/releases/download/$version/podman-remote-release-windows_amd64.zip" "release.zip" + DownloadOptional "$base_url/releases/download/$version/shasums" ..\shasums + } + Expand-Archive -Path release.zip + $loc = Get-ChildItem -Recurse -Path . -Name win-sshproxy.exe + if (!$loc) { + if ($releaseDir.Length -gt 0) { + throw "Release dir only supports zip which includes win-sshproxy.exe" + } + Write-Host "Old release, zip does not include win-sshproxy.exe, fetching via msi" + DownloadOrSkip "$base_url/releases/download/$version/podman-$version.msi" "podman.msi" + dark -x expand ./podman.msi + if (!$?) { + throw "Dark command failed" + } + $loc = Get-ChildItem -Recurse -Path expand -Name 4A2AD125-34E7-4BD8-BE28-B2A9A5EDBEB5 + if (!$loc) { + throw "Could not obtain win-sshproxy.exe" + } + Copy-Item -Path "expand\$loc" -Destination "win-sshproxy.exe" -ErrorAction Stop + Remove-Item -Recurse -Force -Path expand + } + + Write-Host "Copying artifacts" + Foreach ($fileName in "win-sshproxy.exe", "podman.exe") { + Copy-Artifact($fileName) + } + + $docsloc = Get-ChildItem -Path . -Name docs -Recurse + $loc = Get-ChildItem -Recurse -Path . -Name podman-for-windows.html + if (!$loc) { + Write-Host "Old release did not include welcome page, using podman-machine instead" + $loc = Get-ChildItem -Recurse -Path . -Name podman-machine.html + Copy-Item -Path $loc -Destination "$docsloc\podman-for-windows.html" + } + + Write-Host "Copying docs" + Copy-Item -Recurse -Path $docsloc -Destination ..\docs -ErrorAction Stop + Write-Host "Done!" + + if (!$loc) { + throw "Could not find docs" + } +} +catch { + Write-Host $_ + + $exitCode = 1 +} +finally { + if ($restore) { + Pop-Location + } +} + +exit $exitCode diff --git a/contrib/win-installer/resources/podman-banner.png b/contrib/win-installer/resources/podman-banner.png Binary files differnew file mode 100644 index 000000000..e5070db98 --- /dev/null +++ b/contrib/win-installer/resources/podman-banner.png diff --git a/contrib/win-installer/resources/podman-banner2.png b/contrib/win-installer/resources/podman-banner2.png Binary files differnew file mode 100644 index 000000000..88ee1bfad --- /dev/null +++ b/contrib/win-installer/resources/podman-banner2.png diff --git a/contrib/win-installer/resources/podman-dialog.png b/contrib/win-installer/resources/podman-dialog.png Binary files differnew file mode 100644 index 000000000..cf0c49d98 --- /dev/null +++ b/contrib/win-installer/resources/podman-dialog.png diff --git a/contrib/win-installer/resources/podman-logo.ico b/contrib/win-installer/resources/podman-logo.ico Binary files differnew file mode 100644 index 000000000..cb1dab6a7 --- /dev/null +++ b/contrib/win-installer/resources/podman-logo.ico diff --git a/contrib/win-installer/resources/podman-logo.png b/contrib/win-installer/resources/podman-logo.png Binary files differnew file mode 100644 index 000000000..5df6453a8 --- /dev/null +++ b/contrib/win-installer/resources/podman-logo.png diff --git a/contrib/win-installer/resources/podman-sidebar.png b/contrib/win-installer/resources/podman-sidebar.png Binary files differnew file mode 100644 index 000000000..cc0249706 --- /dev/null +++ b/contrib/win-installer/resources/podman-sidebar.png diff --git a/contrib/win-installer/welcome-install-dlg.wxs b/contrib/win-installer/welcome-install-dlg.wxs new file mode 100644 index 000000000..cc0f1c643 --- /dev/null +++ b/contrib/win-installer/welcome-install-dlg.wxs @@ -0,0 +1,31 @@ +<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> + <Fragment> + <UI> + <Dialog Id="WelcomeInstallDlg" Width="370" Height="270" Title="!(loc.WelcomeDlg_Title)"> + <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.WelcomeDlgBitmap)" /> + <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.WelcomeDlgTitle)" /> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" /> + <Control Id="Description" Type="Text" X="135" Y="80" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.WelcomeDlgDescription)" /> + <Control Id="WSLInstallCheckbox" Type="CheckBox" X="135" Y="135" Width="226" Height="18" CheckBoxValue="1" Property="WSL_INSTALL" Default="no" Text="Install WSL Feature (if needed)" /> + + <Control Id="Back" Type="PushButton" X="156" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUIBack)"/> + <Control Id="Install" Type="PushButton" ElevationShield="yes" X="212" Y="243" Width="80" Height="17" Default="yes" Text="!(loc.WelcomeEulaDlgInstall)"> + <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">!(wix.WixUICostingPopupOptOut) OR CostingComplete = 1</Publish> + <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace <> 1]]></Publish> + <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)</Publish> + <Publish Event="EndDialog" Value="Return">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="EnableRollback" Value="False">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish> + <Publish Event="SpawnDialog" Value="OutOfDiskDlg">(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")</Publish> + </Control> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)"> + <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish> + </Control> + + </Dialog> + </UI> + + <InstallUISequence> + <Show Dialog="WelcomeInstallDlg" Before="ProgressDlg" Overridable="yes">NOT Installed</Show> + </InstallUISequence> + </Fragment> +</Wix> diff --git a/docs/source/markdown/options/privileged.md b/docs/source/markdown/options/privileged.md new file mode 100644 index 000000000..8d9746d6b --- /dev/null +++ b/docs/source/markdown/options/privileged.md @@ -0,0 +1,14 @@ +#### **--privileged** + +Give extended privileges to this container. The default is **false**. + +By default, Podman containers are unprivileged (**=false**) and cannot, for +example, modify parts of the operating system. This is because by default a +container is only allowed limited access to devices. A "privileged" container +is given the same access to devices as the user launching the container. + +A privileged container turns off the security features that isolate the +container from the host. Dropped Capabilities, limited devices, read-only mount +points, Apparmor/SELinux separation, and Seccomp filters are all disabled. + +Rootless containers cannot have more privileges than the account that launched them. diff --git a/docs/source/markdown/options/sysctl.md b/docs/source/markdown/options/sysctl.md new file mode 100644 index 000000000..6fc1bbebe --- /dev/null +++ b/docs/source/markdown/options/sysctl.md @@ -0,0 +1,21 @@ +#### **--sysctl**=*name=value* + +Configure namespaced kernel parameters <<at runtime|for all containers in the pod>>. + +For the IPC namespace, the following sysctls are allowed: + +- kernel.msgmax +- kernel.msgmnb +- kernel.msgmni +- kernel.sem +- kernel.shmall +- kernel.shmmax +- kernel.shmmni +- kernel.shm_rmid_forced +- Sysctls beginning with fs.mqueue.\* + +Note: <<if you use the **--ipc=host** option|if the ipc namespace is not shared within the pod>>, the above sysctls are not allowed. + +For the network namespace, only sysctls beginning with net.\* are allowed. + +Note: <<if you use the **--network=host** option|if the network namespace is not shared within the pod>>, the above sysctls are not allowed. diff --git a/docs/source/markdown/options/userns.pod.md b/docs/source/markdown/options/userns.pod.md new file mode 100644 index 000000000..389f47bd5 --- /dev/null +++ b/docs/source/markdown/options/userns.pod.md @@ -0,0 +1,28 @@ +#### **--userns**=*mode* + +Set the user namespace mode for all the containers in a pod. It defaults to the **PODMAN_USERNS** environment variable. An empty value ("") means user namespaces are disabled. + +Rootless user --userns=Key mappings: + +Key | Host User | Container User +----------|---------------|--------------------- +"" |$UID |0 (Default User account mapped to root user in container.) +keep-id |$UID |$UID (Map user account to same UID within container.) +auto |$UID | nil (Host User UID is not mapped into container.) +nomap |$UID | nil (Host User UID is not mapped into container.) + +Valid _mode_ values are: + + - *auto[:*_OPTIONS,..._*]*: automatically create a namespace. It is possible to specify these options to `auto`: + + - *gidmapping=*_CONTAINER_GID:HOST_GID:SIZE_ to force a GID mapping to be present in the user namespace. + + - *size=*_SIZE_: to specify an explicit size for the automatic user namespace. e.g. `--userns=auto:size=8192`. If `size` is not specified, `auto` will estimate a size for the user namespace. + + - *uidmapping=*_CONTAINER_UID:HOST_UID:SIZE_ to force a UID mapping to be present in the user namespace. + + - *host*: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default). + + - *keep-id*: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is not allowed for containers created by the root user. + + - *nomap*: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is not allowed for containers created by the root user. diff --git a/docs/source/markdown/podman-create.1.md.in b/docs/source/markdown/podman-create.1.md.in index ac45fa61d..a20aeafcd 100644 --- a/docs/source/markdown/podman-create.1.md.in +++ b/docs/source/markdown/podman-create.1.md.in @@ -354,21 +354,7 @@ To make a pod with more granular options, use the `podman pod create` command be @@option pod-id-file.container -#### **--privileged** - -Give extended privileges to this container. The default is *false*. - -By default, Podman containers are -“unprivileged” (=false) and cannot, for example, modify parts of the operating system. -This is because by default a container is not allowed to access any devices. -A “privileged” container is given access to all devices. - -When the operator executes a privileged container, Podman enables access -to all devices on the host, turns off graphdriver mount options, as well as -turning off most of the security measures protecting the host from the -container. - -Rootless containers cannot have more privileges than the account that launched them. +@@option privileged #### **--publish**, **-p**=*[[ip:][hostPort]:]containerPort[/protocol]* @@ -500,21 +486,7 @@ When size is `0`, there is no limit on the amount of memory used for IPC by the @@option subuidname -#### **--sysctl**=*SYSCTL* - -Configure namespaced kernel parameters at runtime - -IPC Namespace - current sysctls allowed: - -kernel.msgmax, kernel.msgmnb, kernel.msgmni, kernel.sem, kernel.shmall, kernel.shmmax, kernel.shmmni, kernel.shm_rmid_forced -Sysctls beginning with fs.mqueue.* - -Note: if you use the --ipc=host option these sysctls will not be allowed. - -Network Namespace - current sysctls allowed: - Sysctls beginning with net.* - -Note: if you use the --network=host option these sysctls will not be allowed. +@@option sysctl @@option systemd diff --git a/docs/source/markdown/podman-exec.1.md.in b/docs/source/markdown/podman-exec.1.md.in index 3202159c9..0d161ef66 100644 --- a/docs/source/markdown/podman-exec.1.md.in +++ b/docs/source/markdown/podman-exec.1.md.in @@ -44,21 +44,7 @@ to run containers such as CRI-O, the last started container could be from either Pass down to the process N additional file descriptors (in addition to 0, 1, 2). The total FDs will be 3+N. -#### **--privileged** - -Give extended privileges to this container. The default is *false*. - -By default, Podman containers are -"unprivileged" and cannot, for example, modify parts of the operating system. -This is because by default a container is only allowed limited access to devices. -A "privileged" container is given the same access to devices as the user launching the container. - -A privileged container turns off the security features that isolate the -container from the host. Dropped Capabilities, limited devices, read/only mount -points, Apparmor/SELinux separation, and Seccomp filters are all disabled. - -Rootless containers cannot have more privileges than the account that launched them. - +@@option privileged #### **--tty**, **-t** diff --git a/docs/source/markdown/podman-pod-clone.1.md.in b/docs/source/markdown/podman-pod-clone.1.md.in index 32183d778..011efc5b7 100644 --- a/docs/source/markdown/podman-pod-clone.1.md.in +++ b/docs/source/markdown/podman-pod-clone.1.md.in @@ -114,58 +114,11 @@ clone process has completed. All containers within the pod are started. @@option subuidname -#### **--sysctl**=*name=value* - -Configure namespace kernel parameters for all containers in the new pod. - -For the IPC namespace, the following sysctls are allowed: - -- kernel.msgmax -- kernel.msgmnb -- kernel.msgmni -- kernel.sem -- kernel.shmall -- kernel.shmmax -- kernel.shmmni -- kernel.shm_rmid_forced -- Sysctls beginning with fs.mqueue.\* - -Note: if the ipc namespace is not shared within the pod, these sysctls are not allowed. - -For the network namespace, only sysctls beginning with net.\* are allowed. - -Note: if the network namespace is not shared within the pod, these sysctls are not allowed. +@@option sysctl @@option uidmap.pod -#### **--userns**=*mode* - -Set the user namespace mode for all the containers in a pod. It defaults to the **PODMAN_USERNS** environment variable. An empty value ("") means user namespaces are disabled. - -Rootless user --userns=Key mappings: - -Key | Host User | Container User -----------|---------------|--------------------- -"" |$UID |0 (Default User account mapped to root user in container.) -keep-id |$UID |$UID (Map user account to same UID within container.) -auto |$UID | nil (Host User UID is not mapped into container.) -nomap |$UID | nil (Host User UID is not mapped into container.) - -Valid _mode_ values are: - - - *auto[:*_OPTIONS,..._*]*: automatically create a namespace. It is possible to specify these options to `auto`: - - - *gidmapping=*_CONTAINER_GID:HOST_GID:SIZE_ to force a GID mapping to be present in the user namespace. - - - *size=*_SIZE_: to specify an explicit size for the automatic user namespace. e.g. `--userns=auto:size=8192`. If `size` is not specified, `auto` will estimate a size for the user namespace. - - - *uidmapping=*_CONTAINER_UID:HOST_UID:SIZE_ to force a UID mapping to be present in the user namespace. - - - *host*: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default). - - - *keep-id*: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is ignored for containers created by the root user. - - - *nomap*: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is ignored for containers created by the root user. +@@option userns.pod @@option uts.pod diff --git a/docs/source/markdown/podman-pod-create.1.md.in b/docs/source/markdown/podman-pod-create.1.md.in index b747022eb..24edbb918 100644 --- a/docs/source/markdown/podman-pod-create.1.md.in +++ b/docs/source/markdown/podman-pod-create.1.md.in @@ -255,58 +255,11 @@ When size is `0`, there is no limit on the amount of memory used for IPC by the @@option subuidname -#### **--sysctl**=*name=value* - -Configure namespace kernel parameters for all containers in the pod. - -For the IPC namespace, the following sysctls are allowed: - -- kernel.msgmax -- kernel.msgmnb -- kernel.msgmni -- kernel.sem -- kernel.shmall -- kernel.shmmax -- kernel.shmmni -- kernel.shm_rmid_forced -- Sysctls beginning with fs.mqueue.\* - -Note: if the ipc namespace is not shared within the pod, these sysctls are not allowed. - -For the network namespace, only sysctls beginning with net.\* are allowed. - -Note: if the network namespace is not shared within the pod, these sysctls are not allowed. +@@option sysctl @@option uidmap.pod -#### **--userns**=*mode* - -Set the user namespace mode for all the containers in a pod. It defaults to the **PODMAN_USERNS** environment variable. An empty value ("") means user namespaces are disabled. - -Rootless user --userns=Key mappings: - -Key | Host User | Container User -----------|---------------|--------------------- -"" |$UID |0 (Default User account mapped to root user in container.) -keep-id |$UID |$UID (Map user account to same UID within container.) -auto |$UID | nil (Host User UID is not mapped into container.) -nomap |$UID | nil (Host User UID is not mapped into container.) - -Valid _mode_ values are: - - - *auto[:*_OPTIONS,..._*]*: automatically create a namespace. It is possible to specify these options to `auto`: - - - *gidmapping=*_CONTAINER_GID:HOST_GID:SIZE_ to force a GID mapping to be present in the user namespace. - - - *size=*_SIZE_: to specify an explicit size for the automatic user namespace. e.g. `--userns=auto:size=8192`. If `size` is not specified, `auto` will estimate a size for the user namespace. - - - *uidmapping=*_CONTAINER_UID:HOST_UID:SIZE_ to force a UID mapping to be present in the user namespace. - - - *host*: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default). - - - *keep-id*: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is not allowed for containers created by the root user. - - - *nomap*: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is not allowed for containers created by the root user. +@@option userns.pod @@option uts.pod diff --git a/docs/source/markdown/podman-run.1.md.in b/docs/source/markdown/podman-run.1.md.in index d9b4fe5c3..2bb3098e2 100644 --- a/docs/source/markdown/podman-run.1.md.in +++ b/docs/source/markdown/podman-run.1.md.in @@ -385,20 +385,7 @@ If a container is run with a pod, and the pod has an infra-container, the infra- Pass down to the process N additional file descriptors (in addition to 0, 1, 2). The total FDs will be 3+N. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) -#### **--privileged** - -Give extended privileges to this container. The default is **false**. - -By default, Podman containers are unprivileged (**=false**) and cannot, for -example, modify parts of the operating system. This is because by default a -container is only allowed limited access to devices. A "privileged" container -is given the same access to devices as the user launching the container. - -A privileged container turns off the security features that isolate the -container from the host. Dropped Capabilities, limited devices, read-only mount -points, Apparmor/SELinux separation, and Seccomp filters are all disabled. - -Rootless containers cannot have more privileges than the account that launched them. +@@option privileged #### **--publish**, **-p**=*[[ip:][hostPort]:]containerPort[/protocol]* @@ -542,29 +529,7 @@ Sets whether the signals sent to the **podman run** command are proxied to the c @@option subuidname -#### **--sysctl**=*name=value* - -Configure namespaced kernel parameters at runtime. - -For the IPC namespace, the following sysctls are allowed: - -- kernel.msgmax -- kernel.msgmnb -- kernel.msgmni -- kernel.sem -- kernel.shmall -- kernel.shmmax -- kernel.shmmni -- kernel.shm_rmid_forced -- Sysctls beginning with fs.mqueue.\* - -Note: if you use the **--ipc=host** option, the above sysctls will not be allowed. - -For the network namespace, the following sysctls are allowed: - -- Sysctls beginning with net.\* - -Note: if you use the **--network=host** option, these sysctls will not be allowed. +@@option sysctl @@option systemd diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 83882ecac..9b05a2d61 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -4,6 +4,7 @@ package libpod import ( + "errors" "fmt" "os" "path" @@ -266,9 +267,15 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro g.AddMount(systemdMnt) } else { mountOptions := []string{"bind", "rprivate"} + skipMount := false var statfs unix.Statfs_t if err := unix.Statfs("/sys/fs/cgroup/systemd", &statfs); err != nil { + if errors.Is(err, os.ErrNotExist) { + // If the mount is missing on the host, we cannot bind mount it so + // just skip it. + skipMount = true + } mountOptions = append(mountOptions, "nodev", "noexec", "nosuid") } else { if statfs.Flags&unix.MS_NODEV == unix.MS_NODEV { @@ -284,15 +291,16 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro mountOptions = append(mountOptions, "ro") } } - - systemdMnt := spec.Mount{ - Destination: "/sys/fs/cgroup/systemd", - Type: "bind", - Source: "/sys/fs/cgroup/systemd", - Options: mountOptions, + if !skipMount { + systemdMnt := spec.Mount{ + Destination: "/sys/fs/cgroup/systemd", + Type: "bind", + Source: "/sys/fs/cgroup/systemd", + Options: mountOptions, + } + g.AddMount(systemdMnt) + g.AddLinuxMaskedPaths("/sys/fs/cgroup/systemd/release_agent") } - g.AddMount(systemdMnt) - g.AddLinuxMaskedPaths("/sys/fs/cgroup/systemd/release_agent") } return nil diff --git a/pkg/bindings/system/system.go b/pkg/bindings/system/system.go index dae80384b..733b2cb5c 100644 --- a/pkg/bindings/system/system.go +++ b/pkg/bindings/system/system.go @@ -36,8 +36,9 @@ func Events(ctx context.Context, eventChan chan entities.Event, cancelChan chan if cancelChan != nil { go func() { <-cancelChan - err = response.Body.Close() - logrus.Errorf("Unable to close event response body: %v", err) + if err := response.Body.Close(); err != nil { + logrus.Errorf("Unable to close event response body: %v", err) + } }() } diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index 8b6d74817..7e453823f 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -638,13 +638,13 @@ func installScripts(dist string) error { } func checkAndInstallWSL(opts machine.InitOptions) (bool, error) { - if isWSLInstalled() { + if IsWSLInstalled() { return true, nil } admin := hasAdminRights() - if !isWSLFeatureEnabled() { + if !IsWSLFeatureEnabled() { return false, attemptFeatureInstall(opts, admin) } @@ -1105,9 +1105,10 @@ func waitPipeExists(pipeName string, retries int, checkFailure func() error) err return err } -func isWSLInstalled() bool { - cmd := exec.Command("wsl", "--status") +func IsWSLInstalled() bool { + cmd := SilentExecCmd("wsl", "--status") out, err := cmd.StdoutPipe() + cmd.Stderr = nil if err != nil { return false } @@ -1131,9 +1132,8 @@ func isWSLInstalled() bool { return true } -func isWSLFeatureEnabled() bool { - cmd := exec.Command("wsl", "--set-default-version", "2") - return cmd.Run() == nil +func IsWSLFeatureEnabled() bool { + return SilentExec("wsl", "--set-default-version", "2") == nil } func isWSLRunning(dist string) (bool, error) { diff --git a/pkg/machine/wsl/util_windows.go b/pkg/machine/wsl/util_windows.go index 6c74e5652..6613bde1f 100644 --- a/pkg/machine/wsl/util_windows.go +++ b/pkg/machine/wsl/util_windows.go @@ -6,6 +6,7 @@ import ( "fmt" "io/ioutil" "os" + "os/exec" "path/filepath" "strings" "syscall" @@ -343,3 +344,17 @@ func sendQuit(tid uint32) { postMessage := user32.NewProc("PostThreadMessageW") postMessage.Call(uintptr(tid), WM_QUIT, 0, 0) } + +func SilentExec(command string, args ...string) error { + cmd := exec.Command(command, args...) + cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: 0x08000000} + cmd.Stdout = nil + cmd.Stderr = nil + return cmd.Run() +} + +func SilentExecCmd(command string, args ...string) *exec.Cmd { + cmd := exec.Command(command, args...) + cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: 0x08000000} + return cmd +} diff --git a/test/e2e/run_staticip_test.go b/test/e2e/run_staticip_test.go index 8207f6d0b..12783cd29 100644 --- a/test/e2e/run_staticip_test.go +++ b/test/e2e/run_staticip_test.go @@ -105,6 +105,13 @@ var _ = Describe("Podman run with --ip flag", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + // We need to set "no_proxy" in proxy environment + if env, found := os.LookupEnv("no_proxy"); found { + defer os.Setenv("no_proxy", env) + } else { + defer os.Unsetenv("no_proxy") + } + os.Setenv("no_proxy", ip) for retries := 20; retries > 0; retries-- { response, err := http.Get(fmt.Sprintf("http://%s", ip)) if err == nil && response.StatusCode == http.StatusOK { diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats index 584511388..1148aaae7 100644 --- a/test/system/001-basic.bats +++ b/test/system/001-basic.bats @@ -190,7 +190,9 @@ See 'podman version --help'" "podman version --remote" run_podman --log-level=error info run_podman --log-level=fatal info run_podman --log-level=panic info + # docker compat run_podman --debug info + run_podman -D info run_podman 1 --debug --log-level=panic info is "$output" "Setting --log-level and --debug is not allowed" } diff --git a/vendor/golang.org/x/sys/windows/svc/eventlog/install.go b/vendor/golang.org/x/sys/windows/svc/eventlog/install.go new file mode 100644 index 000000000..43e324f4b --- /dev/null +++ b/vendor/golang.org/x/sys/windows/svc/eventlog/install.go @@ -0,0 +1,81 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows +// +build windows + +package eventlog + +import ( + "errors" + + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" +) + +const ( + // Log levels. + Info = windows.EVENTLOG_INFORMATION_TYPE + Warning = windows.EVENTLOG_WARNING_TYPE + Error = windows.EVENTLOG_ERROR_TYPE +) + +const addKeyName = `SYSTEM\CurrentControlSet\Services\EventLog\Application` + +// Install modifies PC registry to allow logging with an event source src. +// It adds all required keys and values to the event log registry key. +// Install uses msgFile as the event message file. If useExpandKey is true, +// the event message file is installed as REG_EXPAND_SZ value, +// otherwise as REG_SZ. Use bitwise of log.Error, log.Warning and +// log.Info to specify events supported by the new event source. +func Install(src, msgFile string, useExpandKey bool, eventsSupported uint32) error { + appkey, err := registry.OpenKey(registry.LOCAL_MACHINE, addKeyName, registry.CREATE_SUB_KEY) + if err != nil { + return err + } + defer appkey.Close() + + sk, alreadyExist, err := registry.CreateKey(appkey, src, registry.SET_VALUE) + if err != nil { + return err + } + defer sk.Close() + if alreadyExist { + return errors.New(addKeyName + `\` + src + " registry key already exists") + } + + err = sk.SetDWordValue("CustomSource", 1) + if err != nil { + return err + } + if useExpandKey { + err = sk.SetExpandStringValue("EventMessageFile", msgFile) + } else { + err = sk.SetStringValue("EventMessageFile", msgFile) + } + if err != nil { + return err + } + err = sk.SetDWordValue("TypesSupported", eventsSupported) + if err != nil { + return err + } + return nil +} + +// InstallAsEventCreate is the same as Install, but uses +// %SystemRoot%\System32\EventCreate.exe as the event message file. +func InstallAsEventCreate(src string, eventsSupported uint32) error { + return Install(src, "%SystemRoot%\\System32\\EventCreate.exe", true, eventsSupported) +} + +// Remove deletes all registry elements installed by the correspondent Install. +func Remove(src string) error { + appkey, err := registry.OpenKey(registry.LOCAL_MACHINE, addKeyName, registry.SET_VALUE) + if err != nil { + return err + } + defer appkey.Close() + return registry.DeleteKey(appkey, src) +} diff --git a/vendor/golang.org/x/sys/windows/svc/eventlog/log.go b/vendor/golang.org/x/sys/windows/svc/eventlog/log.go new file mode 100644 index 000000000..f37b4b510 --- /dev/null +++ b/vendor/golang.org/x/sys/windows/svc/eventlog/log.go @@ -0,0 +1,70 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows +// +build windows + +// Package eventlog implements access to Windows event log. +package eventlog + +import ( + "errors" + "syscall" + + "golang.org/x/sys/windows" +) + +// Log provides access to the system log. +type Log struct { + Handle windows.Handle +} + +// Open retrieves a handle to the specified event log. +func Open(source string) (*Log, error) { + return OpenRemote("", source) +} + +// OpenRemote does the same as Open, but on different computer host. +func OpenRemote(host, source string) (*Log, error) { + if source == "" { + return nil, errors.New("Specify event log source") + } + var s *uint16 + if host != "" { + s = syscall.StringToUTF16Ptr(host) + } + h, err := windows.RegisterEventSource(s, syscall.StringToUTF16Ptr(source)) + if err != nil { + return nil, err + } + return &Log{Handle: h}, nil +} + +// Close closes event log l. +func (l *Log) Close() error { + return windows.DeregisterEventSource(l.Handle) +} + +func (l *Log) report(etype uint16, eid uint32, msg string) error { + ss := []*uint16{syscall.StringToUTF16Ptr(msg)} + return windows.ReportEvent(l.Handle, etype, 0, eid, 0, 1, 0, &ss[0], nil) +} + +// Info writes an information event msg with event id eid to the end of event log l. +// When EventCreate.exe is used, eid must be between 1 and 1000. +func (l *Log) Info(eid uint32, msg string) error { + return l.report(windows.EVENTLOG_INFORMATION_TYPE, eid, msg) +} + +// Warning writes an warning event msg with event id eid to the end of event log l. +// When EventCreate.exe is used, eid must be between 1 and 1000. +func (l *Log) Warning(eid uint32, msg string) error { + return l.report(windows.EVENTLOG_WARNING_TYPE, eid, msg) +} + +// Error writes an error event msg with event id eid to the end of event log l. +// When EventCreate.exe is used, eid must be between 1 and 1000. +func (l *Log) Error(eid uint32, msg string) error { + return l.report(windows.EVENTLOG_ERROR_TYPE, eid, msg) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index cc3d7b6a7..f1d4758e4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -794,6 +794,7 @@ golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows golang.org/x/sys/windows/registry +golang.org/x/sys/windows/svc/eventlog # golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 ## explicit golang.org/x/term |