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

Install scripts should always fetch and verify checksums. #2824

Merged
merged 2 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 37 additions & 23 deletions installers/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -113,40 +113,54 @@ function error([string] $msg)
Write-Host $msg -ForegroundColor Red
}

if (!$script:VERSION) {
$version = $script:VERSION
if (!$version) {
# If the user did not specify a version, formulate a query to fetch the JSON info of the latest
# version, including where it is.
$jsonURL = "$script:BASEINFOURL/?channel=$script:CHANNEL&platform=windows&source=install"
} elseif (!($script:VERSION | Select-String -Pattern "-SHA" -SimpleMatch)) {
} elseif (!($version | Select-String -Pattern "-SHA" -SimpleMatch)) {
# If the user specified a partial version (i.e. no SHA), formulate a query to fetch the JSON
# info of that version's latest SHA, including where it is.
$jsonURL = "$script:BASEINFOURL/?channel=$script:CHANNEL&platform=windows&source=install&target-version=$script:VERSION"
$versionNoSHA = $version
$version = ""
$jsonURL = "$script:BASEINFOURL/?channel=$script:CHANNEL&platform=windows&source=install&target-version=$versionNoSHA"
} else {
# If the user specified a full version with SHA, formulate a query to fetch the JSON info of
# that version.
$versionNoSHA = $version -replace "-SHA.*", ""
$jsonURL = "$script:BASEINFOURL/?channel=$script:CHANNEL&platform=windows&source=install&target-version=$versionNoSHA"
Comment on lines +130 to +131
Copy link
Member

Choose a reason for hiding this comment

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

This means that we basically ignore the SHA part. I think we should at least verify that the returned info matches the SHA in this scenario.

}

if ($jsonURL) {
# If the user specified no version or a partial version we need to use the json URL to get the
# actual installer URL.
try {
$infoJson = ConvertFrom-Json -InputObject (download $jsonURL)
} catch [System.Exception] {
}
if (!$infoJson) {
if (!$script:VERSION) {
# Fetch version info.
try {
$infoJson = ConvertFrom-Json -InputObject (download $jsonURL)
} catch [System.Exception] {
Copy link
Member

Choose a reason for hiding this comment

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

I think we should report what the exception was, otherwise debugging will be painful.

Copy link
Contributor Author

@mitchell-as mitchell-as Oct 17, 2023

Choose a reason for hiding this comment

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

Exceptions are output to stdout, so there's no need for additional work. I tested this and it's pretty clear what the issue is (e.g. network unreachable). Or do you mean reported to us via rollbar or something?

}
if (!$infoJson) {
if (!$version) {
Write-Error "Unable to retrieve the latest version number"
} else {
} else {
Write-Error "Could not download a State Tool Installer for the given command line arguments"
}
Write-Error $_.Exception.Message
exit 1
}
Write-Error $_.Exception.Message
exit 1
}

# Extract checksum.
$checksum = $infoJson.Sha256

if (!$version) {
# If the user specified no version or a partial version we need to use the json URL to get the
# actual installer URL.
$version = $infoJson.Version
$checksum = $infoJson.Sha256
$relUrl = $infoJson.Path
} else {
# If the user specified a full version, strip the SHA to get the folder name of the installer
# URL. Then we can construct the installer URL.
$versionNoSHA = $script:VERSION -replace "-SHA.*", ""
$relUrl = "$script:CHANNEL/$versionNoSHA/windows-amd64/state-windows-amd64-$script:VERSION.zip"
# If the user specified a full version, construct the installer URL.
if ($version -ne $infoJson.Version) {
Write-Error "Unknown version: $version"
exit 1
}
$relUrl = "$script:CHANNEL/$versionNoSHA/windows-amd64/state-windows-amd64-$version.zip"
}

# Fetch the requested or latest version.
Expand All @@ -167,9 +181,9 @@ catch [System.Exception]
exit 1
}

# Verify checksum if possible.
# Verify checksum.
$hash = (Get-FileHash -Path $zipPath -Algorithm SHA256).Hash
if ($checksum -and $hash -ne $checksum)
if ($hash -ne $checksum)
{
Write-Warning "SHA256 sum did not match:"
Write-Warning "Expected: $checksum"
Expand Down
43 changes: 26 additions & 17 deletions installers/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -117,32 +117,41 @@ if [ -z "$VERSION" ]; then
elif [ -z "`echo $VERSION | grep -o '\-SHA'`" ]; then
# If the user specified a partial version (i.e. no SHA), formulate a query to fetch the JSON info
# of that version's latest SHA, including where it is.
JSONURL="$BASE_INFO_URL?channel=$CHANNEL&source=install&platform=$OS&target-version=$VERSION"
VERSIONNOSHA="$VERSION"
VERSION=""
JSONURL="$BASE_INFO_URL?channel=$CHANNEL&source=install&platform=$OS&target-version=$VERSIONNOSHA"
else
# If the user specified a full version with SHA, formulate a query to fetch the JSON info of that
# version.
VERSIONNOSHA="`echo $VERSION | sed 's/-SHA.*$//'`"
JSONURL="$BASE_INFO_URL?channel=$CHANNEL&source=install&platform=$OS&target-version=$VERSIONNOSHA"
Comment on lines +126 to +127
Copy link
Member

Choose a reason for hiding this comment

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

This means that we basically ignore the SHA part. I think we should at least verify that the returned info matches the SHA in this scenario.

fi

# Fetch version info.
$FETCH $INSTALLERTMPDIR/info.json $JSONURL || exit 1
if [ ! -z "`grep -o Invalid $INSTALLERTMPDIR/info.json`" ]; then
error "Could not download a State Tool installer for the given command line arguments"
exit 1
fi

if [ ! -z "$JSONURL" ]; then
# Extract checksum.
SUM=`cat $INSTALLERTMPDIR/info.json | sed -ne 's/.*"sha256":[ \t]*"\([^"]*\)".*/\1/p'`

if [ -z "$VERSION" ]; then
# If the user specified no version or a partial version we need to use the json URL to get the
# actual installer URL.
$FETCH $INSTALLERTMPDIR/info.json $JSONURL || exit 1
if [ ! -z "`grep -o Invalid $INSTALLERTMPDIR/info.json`" ]; then
error "Could not download a State Tool installer for the given command line arguments"
exit 1
fi

# Parse info.
VERSION=`cat $INSTALLERTMPDIR/info.json | sed -ne 's/.*"version":[ \t]*"\([^"]*\)".*/\1/p'`
if [ -z "$VERSION" ]; then
error "Unable to retrieve the latest version number"
exit 1
fi
SUM=`cat $INSTALLERTMPDIR/info.json | sed -ne 's/.*"sha256":[ \t]*"\([^"]*\)".*/\1/p'`
RELURL=`cat $INSTALLERTMPDIR/info.json | sed -ne 's/.*"path":[ \t]*"\([^"]*\)".*/\1/p'`
rm $INSTALLERTMPDIR/info.json

else
# If the user specified a full version, strip the SHA to get the folder name of the installer URL.
# Then we can construct the installer URL.
VERSIONNOSHA="`echo $VERSION | sed 's/-SHA.*$//'`"
# If the user specified a full version, construct the installer URL.
if [ "$VERSION" != "`cat $INSTALLERTMPDIR/info.json | sed -ne 's/.*"version":[ \t]*"\([^"]*\)".*/\1/p'`" ]; then
error "Unknown version: $VERSION"
exit 1
fi
RELURL="$CHANNEL/$VERSIONNOSHA/$OS-amd64/state-$OS-amd64-$VERSION$DOWNLOADEXT"
fi

Expand All @@ -162,8 +171,8 @@ if [ $? -ne 0 -o \( "`echo $FETCH | grep -o 'curl'`" = "curl" -a ! -z "`grep -o
exit 1
fi

# Verify checksum if possible.
if [ ! -z "$SUM" -a "`$SHA256SUM -b $INSTALLERTMPDIR/$ARCHIVE | cut -d ' ' -f1`" != "$SUM" ]; then
# Verify checksum.
if [ "`$SHA256SUM -b $INSTALLERTMPDIR/$ARCHIVE | cut -d ' ' -f1`" != "$SUM" ]; then
error "SHA256 sum did not match:"
error "Expected: $SUM"
error "Received: `$SHA256SUM -b $INSTALLERTMPDIR/$ARCHIVE | cut -d ' ' -f1`"
Expand Down
Loading