Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build windows msi for arm and amd #1796

Merged
merged 21 commits into from
Aug 7, 2024
Merged

Conversation

James-Pickett
Copy link
Contributor

@James-Pickett James-Pickett commented Jul 24, 2024

This PR updates package builder to add an arm64 binaries and service config to the MSI. This is done putting both of 2 services / binaries in to the MSI with mutually exclusive conditions based on processor architecture.

To accomplish we are using heat to harvest files set up like ...

└───pkg_root
    └───Launcher-kolide-k2
        ├───bin
        │   ├───amd64
        │   │       launcher.exe
        │   │       osqueryd.exe
        │   │
        │   └───arm64
        │           launcher.exe
        │           osqueryd.exe
        │
        └───conf
                ...

then post processing the generated xml to remove the amd64 and arm64 directory tags so that all the exe files are in the same directory in the xml, then add the mutually exclusive tags to the binary elements

Additionally, the PR adds the windows service recovery settings to go code because the wix extension we were using for that is not compatible with this approach since it's primary key cannot be changed form the service name and would cause unique constraint error (now there are 2 in the MSI). The wix extension for recovery actions is still applied to the amd install.

relates to #1149

pkg/packagekit/wix/service.go Outdated Show resolved Hide resolved
pkg/packaging/packaging.go Outdated Show resolved Hide resolved
pkg/packagekit/wix/wix.go Outdated Show resolved Hide resolved
pkg/packagekit/wix/wix.go Outdated Show resolved Hide resolved
pkg/packagekit/wix/wix.go Outdated Show resolved Hide resolved
pkg/packaging/detectLauncherVersion.go Outdated Show resolved Hide resolved
pkg/packaging/packaging.go Outdated Show resolved Hide resolved
@James-Pickett James-Pickett marked this pull request as ready for review July 25, 2024 22:20
"launcher_arm_version",
env.String("LAUNCHER_ARM_VERSION", "stable"),
"What TUF channel to download launcher from for ARM. Supports filesystem paths",
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this future-proofing in case we want to do more granular releases for launcher in the future (e.g. "bug in launcher version x.y.z on ARM only, so leave stable at x.y.z for all other arches and x.y.y for launcher ARM")? Or are we adding this flag for another reason?

Copy link
Contributor Author

@James-Pickett James-Pickett Jul 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this just so that I could specify a local arm build to package. I can't imagine a situation where we would want the arm and amd binaries to have different code.

This has me thinking though that maybe we should add in some safe guards to ensure the arm and amd versions are the same. If we some how managed to get into a situation where TUF updated one and not the other, we could end up with a package where different arches are on different versions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find a coherent way to verify the versions are the same. However, I set up the flag so that it's default is an empty string and it will just set that flag to what ever launcher_version is if no launcher_arm_version is provided.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure there's a good way to validate a launcher version, without invoking it. Maaaybe we can string parse it, but I'm not sure it's worth it. (And given what Zack recently learned about file versions and MSIs, let's not go there...)

Maybe this is an argument for being less clever. Command line either takes launcher_version= and downloads from TUF (we should have enough metadata there to validate that stable is the same) Or use_local_binary=... and it ignores TUF

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that's kinda what would happen. So maybe I'm over thinking it. Maybe we validate the versions from tuf, and skip that validation on local paths.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invoking it could be troublesome since we'll have 2 binaries with to different arches, An arm64 machine will probably emulate the amd64 binary and run it, but the reverse doesn't work.

I think just having separate flags for paths is probably good with only a single option for launcher_version which is downloaded form tuf for both arches.

pkg/packagekit/wix/service.go Show resolved Hide resolved
pkg/packagekit/wix/wix.go Show resolved Hide resolved
pkg/packaging/packaging.go Outdated Show resolved Hide resolved
@James-Pickett James-Pickett changed the title build msi launcher for arm and amd build windows msi for arm and amd Jul 26, 2024
Copy link
Contributor

@directionless directionless left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cross platform stuff is really neat.

But I'm nervous about moving those restart things out.

cmd/launcher/svc_config_windows.go Outdated Show resolved Hide resolved
"launcher_arm_version",
env.String("LAUNCHER_ARM_VERSION", "stable"),
"What TUF channel to download launcher from for ARM. Supports filesystem paths",
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure there's a good way to validate a launcher version, without invoking it. Maaaybe we can string parse it, but I'm not sure it's worth it. (And given what Zack recently learned about file versions and MSIs, let's not go there...)

Maybe this is an argument for being less clever. Command line either takes launcher_version= and downloads from TUF (we should have enough metadata there to validate that stable is the same) Or use_local_binary=... and it ignores TUF

"launcher_arm_version",
env.String("LAUNCHER_ARM_VERSION", "stable"),
"What TUF channel to download launcher from for ARM. Supports filesystem paths",
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that's kinda what would happen. So maybe I'm over thinking it. Maybe we validate the versions from tuf, and skip that validation on local paths.

@directionless
Copy link
Contributor

Hrm. I kinda want to look at the XML. I know I never baked in something to save it. How do you think that would be to add?

@James-Pickett
Copy link
Contributor Author

James-Pickett commented Jul 29, 2024

Hrm. I kinda want to look at the XML. I know I never baked in something to save it. How do you think that would be to add?

@directionless , there is a flag wix_skip_cleanup already there, I updated it so that it prints the paths to the temp files when clean up gets skipped

@directionless
Copy link
Contributor

Hrm. I kinda want to look at the XML. I know I never baked in something to save it. How do you think that would be to add?

@directionless , there is a flag wix_skip_cleanup already there, I updated it so that it prints the paths to the temp files when clean up gets skipped

Can you attach one here?

@James-Pickett
Copy link
Contributor Author

Hrm. I kinda want to look at the XML. I know I never baked in something to save it. How do you think that would be to add?

@directionless , there is a flag wix_skip_cleanup already there, I updated it so that it prints the paths to the temp files when clean up gets skipped

Can you attach one here?
@directionless

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="PROGDIR">
            <Directory Id="dir9E2FF676320D7BE586E7569535A94904" Name="Launcher-kolide-k2">
                <Directory Id="dir8782311652F143EF6DD238714EB2C5A3" Name="bin">
                        <Component Id="cmpFDADA56D9962ABBCAA5F3803F3A0E022" Guid="84DB7147-05C9-49ED-ACBA-E6CA9AA3C070">
                            <File Id="fil604CDF77A839EF3F45370B06E0D217F0" KeyPath="yes" Source="$(var.SourceDir)\Launcher-kolide-k2\bin\amd64\launcher.exe" />
<Condition> %PROCESSOR_ARCHITECTURE="AMD64" </Condition>
                    <ServiceInstall Account="[SERVICEACCOUNT]" Arguments="svc -config &#34;C:\Program Files\Kolide\Launcher-kolide-k2\conf\launcher.flags&#34;" Description="The Kolide Launcher (kolide-k2)" ErrorControl="normal" Id="LauncherKolideK2Svc01J423A2NVBYJE6VWSZHZAYKK8" Name="LauncherKolideK2Svc" Start="auto" Type="ownProcess" Vital="yes">
                        <ServiceConfig xmlns="http://schemas.microsoft.com/wix/2006/wi" Id="LauncherKolideK2Svc01J423A2NVBYJE6VWSZHZAYKK8" DelayedAutoStart="no" OnInstall="yes" OnReinstall="yes"></ServiceConfig>
                        <ServiceDependency Id="Dnscache" Group="no"></ServiceDependency>
                    </ServiceInstall>
                    <ServiceControl Name="LauncherKolideK2Svc" Id="LauncherKolideK2Svc01J423A2NVBYJE6VWSZHZAYKK8" Remove="uninstall" Start="install" Stop="both" Wait="no"></ServiceControl>
                        </Component>
                        <Component Id="cmp2495C4D31241909F181B39921D2280C9" Guid="03B7DB5F-97AF-46B6-BBC1-C96B7ACEA8BB">
                            <File Id="fil526CC2960E9DEE23BDA92EE29CE5A6A4" KeyPath="yes" Source="$(var.SourceDir)\Launcher-kolide-k2\bin\amd64\osqueryd.exe" />
<Condition> %PROCESSOR_ARCHITECTURE="AMD64" </Condition>
                        </Component>
                        <Component Id="cmpABE14524530AA1F1CB8D6939D826DC32" Guid="F7854DA5-4627-44A8-841B-56BB03F37AB8">
                            <File Id="fil4EFEFF758D7317539AD8F04A59622E4B" KeyPath="yes" Source="$(var.SourceDir)\Launcher-kolide-k2\bin\arm64\launcher.exe" />
<Condition> %PROCESSOR_ARCHITECTURE="ARM64" </Condition>
                    <ServiceInstall Account="[SERVICEACCOUNT]" Arguments="svc -config &#34;C:\Program Files\Kolide\Launcher-kolide-k2\conf\launcher.flags&#34;" Description="The Kolide Launcher (kolide-k2)" ErrorControl="normal" Id="LauncherKolideK2Svc01J423A2NVESRWGYKH5D97DDP4" Name="LauncherKolideK2Svc" Start="auto" Type="ownProcess" Vital="yes">
                        <ServiceConfig xmlns="http://schemas.microsoft.com/wix/2006/wi" Id="LauncherKolideK2Svc01J423A2NVESRWGYKH5D97DDP4" DelayedAutoStart="no" OnInstall="yes" OnReinstall="yes"></ServiceConfig>
                        <ServiceDependency Id="Dnscache" Group="no"></ServiceDependency>
                    </ServiceInstall>
                    <ServiceControl Name="LauncherKolideK2Svc" Id="LauncherKolideK2Svc01J423A2NVESRWGYKH5D97DDP4" Remove="uninstall" Start="install" Stop="both" Wait="no"></ServiceControl>
                        </Component>
                        <Component Id="cmp61B74053A68DD7A35C953D86480F9D4C" Guid="BE7AF4FE-B34C-463A-AE16-A343162B7531">
                            <File Id="fil2A8BBBB8EBD5B626DC98686307B2A9C9" KeyPath="yes" Source="$(var.SourceDir)\Launcher-kolide-k2\bin\arm64\osqueryd.exe" />
<Condition> %PROCESSOR_ARCHITECTURE="ARM64" </Condition>
                        </Component>
                </Directory>
                <Directory Id="dirC586BDDEA1A8C8B62AFD7017E646DD85" Name="conf">
                    <Component Id="cmp3B4F901A7E2AE41959321E267F5FA937" Guid="C2F68C91-D693-4F13-B943-6D108A2CE5D6">
                        <File Id="fil18DE5428F20D530D3039426F03C41AC7" KeyPath="yes" Source="$(var.SourceDir)\Launcher-kolide-k2\conf\launcher.flags" />
                    </Component>
                    <Component Id="cmp9DD41EA0BAC4BB356CB0436EC8BAE15D" Guid="687C5B5A-4071-4EAA-88CA-F475CC9A58DE">
                        <File Id="filB41D4879C4A879139C72198A2D8D7862" KeyPath="yes" Source="$(var.SourceDir)\Launcher-kolide-k2\conf\secret" />
                    </Component>
                </Directory>
            </Directory>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="AppFiles">
            <ComponentRef Id="cmpFDADA56D9962ABBCAA5F3803F3A0E022" />
            <ComponentRef Id="cmp2495C4D31241909F181B39921D2280C9" />
            <ComponentRef Id="cmpABE14524530AA1F1CB8D6939D826DC32" />
            <ComponentRef Id="cmp61B74053A68DD7A35C953D86480F9D4C" />
            <ComponentRef Id="cmp3B4F901A7E2AE41959321E267F5FA937" />
            <ComponentRef Id="cmp9DD41EA0BAC4BB356CB0436EC8BAE15D" />
        </ComponentGroup>
    </Fragment>
</Wix>

@RebeccaMahany RebeccaMahany added the component:build&packaging Build and Package label Aug 1, 2024
Copy link
Contributor

@RebeccaMahany RebeccaMahany left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a couple small comments!

cmd/launcher/svc_config_windows.go Outdated Show resolved Hide resolved
pkg/packagekit/wix/wix.go Show resolved Hide resolved
pkg/packagekit/wix/wix.go Outdated Show resolved Hide resolved
pkg/packagekit/wix/wix.go Outdated Show resolved Hide resolved
pkg/packagekit/wix/wix.go Show resolved Hide resolved
Copy link
Contributor

@RebeccaMahany RebeccaMahany left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥 amazing

Copy link
Contributor

@directionless directionless left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a big step forward.

And I love the conclusion of only removing the util stuff from the less common platform.

// setRecoveryActions sets the recovery actions for the launcher service.
// previously defined via wix ServicConfig Element (Util Extension) https://wixtoolset.org/docs/v3/xsd/util/serviceconfig/
func setRecoveryActions(ctx context.Context, logger *slog.Logger) {
sman, err := mgr.Connect()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this is what we're doing everywhere here, I wonder if we should consolidate and only open it once, instead of the rapid opening and closing. (If we think so, it's fine as a followup)


###### Windows Multi-Archecture MSI

Package builder creates an MSI containing both amd64 & arm64 binaries. This is done putting both of binaries and their service installation in to the MSI with mutually exclusive conditions based on processor architecture.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very clear.

Comment on lines -61 to -65
// Normally we'd download the same version we bake into the
// autoupdate. But occasionally, it's handy to make a package
// with a different version.
LauncherDownloadVersionOverride string
OsqueryDownloadVersionOverride string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's okay to remove these, but I want to note that I have used them in the past. They might make less sense with the newer TUF updater

Copy link
Contributor

@zackattack01 zackattack01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥

@James-Pickett James-Pickett added this pull request to the merge queue Aug 7, 2024
Merged via the queue into kolide:main with commit 1055416 Aug 7, 2024
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component:build&packaging Build and Package
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants