Skip to content

Commit

Permalink
api: add checksum validation in Content Library update session file API
Browse files Browse the repository at this point in the history
  • Loading branch information
dilyar85 authored and dougm committed May 7, 2024
1 parent e6fe159 commit 37269b6
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 6 deletions.
3 changes: 3 additions & 0 deletions govc/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3613,8 +3613,11 @@ Examples:
govc library.import library_name/item_name file.ova # update existing item
govc library.import library_name http://example.com/file.ovf # download and push to vCenter
govc library.import -pull library_name http://example.com/file.ova # direct pull from vCenter
govc library.import -pull -c=<checksum> -a=<SHA1|MD5|SHA256|SHA512> library_name http://example.com/file.ova # direct pull from vCenter with checksum validation
Options:
-a=SHA256 Algorithm used to calculate the checksum. Possible values are: SHA1, MD5, SHA256 (default), SHA512
-c= Checksum value to verify the pulled library item
-m=false Require ova manifest
-n= Library item name
-pull=false Pull library item from http endpoint
Expand Down
20 changes: 17 additions & 3 deletions govc/library/import.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2019 VMware, Inc. All Rights Reserved.
Copyright (c) 2019-2024 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -38,6 +38,7 @@ type item struct {
*flags.ClientFlag
*flags.OutputFlag
library.Item
library.Checksum

manifest bool
pull bool
Expand All @@ -58,6 +59,8 @@ func (cmd *item) Register(ctx context.Context, f *flag.FlagSet) {
f.StringVar(&cmd.Type, "t", "", "Library item type")
f.BoolVar(&cmd.manifest, "m", false, "Require ova manifest")
f.BoolVar(&cmd.pull, "pull", false, "Pull library item from http endpoint")
f.StringVar(&cmd.Checksum.Checksum, "c", "", "Checksum value to verify the pulled library item")
f.StringVar(&cmd.Checksum.Algorithm, "a", "SHA256", "Algorithm used to calculate the checksum. Possible values are: SHA1, MD5, SHA256 (default), SHA512")
}

func (cmd *item) Usage() string {
Expand All @@ -74,7 +77,8 @@ Examples:
govc library.import library_id file.iso # Use library id if multiple libraries have the same name
govc library.import library_name/item_name file.ova # update existing item
govc library.import library_name http://example.com/file.ovf # download and push to vCenter
govc library.import -pull library_name http://example.com/file.ova # direct pull from vCenter`
govc library.import -pull library_name http://example.com/file.ova # direct pull from vCenter
govc library.import -pull -c=<checksum> -a=<SHA1|MD5|SHA256|SHA512> library_name http://example.com/file.ova # direct pull from vCenter with checksum validation`
}

func (cmd *item) Process(ctx context.Context) error {
Expand All @@ -89,6 +93,16 @@ func (cmd *item) Run(ctx context.Context, f *flag.FlagSet) error {
return flag.ErrHelp
}

// Checksums are verified after the file is uploaded to a server.
// Check the algorithm and fail early if it's not supported.
if cmd.pull && cmd.Checksum.Checksum != "" {
switch cmd.Checksum.Algorithm {
case "SHA1", "MD5", "SHA256", "SHA512":
default:
return fmt.Errorf("invalid checksum algorithm: %s", cmd.Checksum.Algorithm)
}
}

file := f.Arg(1)
base := filepath.Base(file)
ext := filepath.Ext(base)
Expand Down Expand Up @@ -172,7 +186,7 @@ func (cmd *item) Run(ctx context.Context, f *flag.FlagSet) error {
return err
}
if cmd.pull {
_, err = m.AddLibraryItemFileFromURI(ctx, session, filepath.Base(file), file)
_, err = m.AddLibraryItemFileFromURI(ctx, session, filepath.Base(file), file, cmd.Checksum)
if err != nil {
return err
}
Expand Down
6 changes: 4 additions & 2 deletions govc/test/library.bats
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ load test_helper
dir=$(govc datastore.info -json | jq -r .datastores[].info.url)
ln -s "$GOVC_IMAGES/$TTYLINUX_NAME."* "$dir"

run govc library.import -pull my-content "https://$(govc env GOVC_URL)/folder/$TTYLINUX_NAME.ovf"
# vcsim doesn't verify checksums. Use a fake checksum and a possible algorithm to ensure the args are accepted.
run govc library.import -pull -c=fake -a=SHA1 my-content "https://$(govc env GOVC_URL)/folder/$TTYLINUX_NAME.ovf"
assert_success

run govc library.deploy "my-content/$TTYLINUX_NAME" ttylinux
Expand All @@ -196,7 +197,8 @@ load test_helper
run govc vm.info ttylinux
assert_success

run govc library.import -pull -n ttylinux-unpacked my-content "https://$(govc env GOVC_URL)/folder/$TTYLINUX_NAME.ova"
# vcsim doesn't verify checksums. Use a fake checksum and a possible algorithm to ensure the args are accepted.
run govc library.import -pull -c=fake -a=MD5 -n ttylinux-unpacked my-content "https://$(govc env GOVC_URL)/folder/$TTYLINUX_NAME.ova"
assert_success

item_id=$(govc library.info -json /my-content/ttylinux-unpacked | jq -r .[].id)
Expand Down
9 changes: 8 additions & 1 deletion vapi/library/library_item_updatesession_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package library
import (
"bufio"
"context"
"fmt"
"io"
"net/http"
"strings"
Expand Down Expand Up @@ -87,7 +88,7 @@ func (c *Manager) AddLibraryItemFile(ctx context.Context, sessionID string, upda
}

// AddLibraryItemFileFromURI adds a file from a remote URI.
func (c *Manager) AddLibraryItemFileFromURI(ctx context.Context, sessionID, name, uri string) (*UpdateFile, error) {
func (c *Manager) AddLibraryItemFileFromURI(ctx context.Context, sessionID, name, uri string, checksum ...Checksum) (*UpdateFile, error) {
source := &TransferEndpoint{
URI: uri,
}
Expand All @@ -98,6 +99,12 @@ func (c *Manager) AddLibraryItemFileFromURI(ctx context.Context, sessionID, name
SourceEndpoint: source,
}

if len(checksum) == 1 && checksum[0].Checksum != "" {
file.Checksum = &checksum[0]
} else if len(checksum) > 1 {
return nil, fmt.Errorf("expected 0 or 1 checksum, got %d", len(checksum))
}

if res, err := c.Head(uri); err == nil {
file.Size = res.ContentLength
if res.TLS != nil {
Expand Down

0 comments on commit 37269b6

Please sign in to comment.