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

Check content-type in importer to warn against unexpected kubevirt imports #2909

Merged
merged 2 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
26 changes: 19 additions & 7 deletions pkg/importer/http-datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ import (
)

const (
tempFile = "tmpimage"
nbdkitPid = "/tmp/nbdkit.pid"
nbdkitSocket = "/tmp/nbdkit.sock"
defaultUserAgent = "cdi-golang-importer"
tempFile = "tmpimage"
nbdkitPid = "/tmp/nbdkit.pid"
nbdkitSocket = "/tmp/nbdkit.sock"
defaultUserAgent = "cdi-golang-importer"
httpContentType = "Content-Type"
httpContentLength = "Content-Length"
)

// HTTPDataSource is the data provider for http(s) endpoints.
Expand Down Expand Up @@ -96,7 +98,7 @@ func NewHTTPDataSource(endpoint, accessKey, secKey, certDir string, contentType
return nil, errors.Wrap(err, "Error getting extra headers for HTTP client")
}

httpReader, contentLength, brokenForQemuImg, err := createHTTPReader(ctx, ep, accessKey, secKey, certDir, extraHeaders, secretExtraHeaders)
httpReader, contentLength, brokenForQemuImg, err := createHTTPReader(ctx, ep, accessKey, secKey, certDir, extraHeaders, secretExtraHeaders, contentType)
if err != nil {
cancel()
return nil, err
Expand Down Expand Up @@ -294,7 +296,7 @@ func addExtraheaders(req *http.Request, extraHeaders []string) {
req.Header.Add("User-Agent", defaultUserAgent)
}

func createHTTPReader(ctx context.Context, ep *url.URL, accessKey, secKey, certDir string, extraHeaders, secretExtraHeaders []string) (io.ReadCloser, uint64, bool, error) {
func createHTTPReader(ctx context.Context, ep *url.URL, accessKey, secKey, certDir string, extraHeaders, secretExtraHeaders []string, contentType cdiv1.DataVolumeContentType) (io.ReadCloser, uint64, bool, error) {
var brokenForQemuImg bool
client, err := createHTTPClient(certDir)
if err != nil {
Expand Down Expand Up @@ -334,6 +336,16 @@ func createHTTPReader(ctx context.Context, ep *url.URL, accessKey, secKey, certD
return nil, uint64(0), true, errors.Errorf("expected status code 200, got %d. Status: %s", resp.StatusCode, resp.Status)
}

if contentType == cdiv1.DataVolumeKubeVirt {
// Check the content-type if we are expecting a KubeVirt img.
if val, ok := resp.Header[httpContentType]; ok {
if strings.HasPrefix(val[0], "text/") {
// We will continue with the import nonetheless, but content might be unexpected.
klog.Warningf("Unexpected content type '%s'. Content might not be a KubeVirt image.", val[0])
}
}
}

acceptRanges, ok := resp.Header["Accept-Ranges"]
if !ok || acceptRanges[0] == "none" {
klog.V(2).Infof("Accept-Ranges isn't bytes, avoiding qemu-img")
Expand Down Expand Up @@ -416,7 +428,7 @@ func getContentLength(client *http.Client, ep *url.URL, accessKey, secKey string
func parseHTTPHeader(resp *http.Response) uint64 {
var err error
total := uint64(0)
if val, ok := resp.Header["Content-Length"]; ok {
if val, ok := resp.Header[httpContentLength]; ok {
total, err = strconv.ParseUint(val[0], 10, 64)
if err != nil {
klog.Errorf("could not convert content length, got %v", err)
Expand Down
18 changes: 9 additions & 9 deletions pkg/importer/http-datasource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ var _ = Describe("Http client", func() {

var _ = Describe("Http reader", func() {
It("should fail when passed an invalid cert directory", func() {
_, total, _, err := createHTTPReader(context.Background(), nil, "", "", "/invalid", nil, nil)
_, total, _, err := createHTTPReader(context.Background(), nil, "", "", "/invalid", nil, nil, cdiv1.DataVolumeKubeVirt)
Expect(err).To(HaveOccurred())
Expect(uint64(0)).To(Equal(total))
})
Expand All @@ -249,7 +249,7 @@ var _ = Describe("Http reader", func() {
defer ts.Close()
ep, err := url.Parse(ts.URL)
Expect(err).ToNot(HaveOccurred())
r, total, _, err := createHTTPReader(context.Background(), ep, "user", "password", "", nil, nil)
r, total, _, err := createHTTPReader(context.Background(), ep, "user", "password", "", nil, nil, cdiv1.DataVolumeKubeVirt)
Expect(err).ToNot(HaveOccurred())
Expect(uint64(25)).To(Equal(total))
err = r.Close()
Expand All @@ -272,7 +272,7 @@ var _ = Describe("Http reader", func() {
defer ts.Close()
ep, err := url.Parse(ts.URL)
Expect(err).ToNot(HaveOccurred())
r, total, _, err := createHTTPReader(context.Background(), ep, "user", "password", "", nil, nil)
r, total, _, err := createHTTPReader(context.Background(), ep, "user", "password", "", nil, nil, cdiv1.DataVolumeKubeVirt)
Expect(err).ToNot(HaveOccurred())
Expect(uint64(25)).To(Equal(total))
err = r.Close()
Expand All @@ -294,7 +294,7 @@ var _ = Describe("Http reader", func() {
defer ts.Close()
ep, err := url.Parse(ts.URL)
Expect(err).ToNot(HaveOccurred())
r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil)
r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt)
Expect(brokenForQemuImg).To(BeFalse())
Expect(err).ToNot(HaveOccurred())
Expect(uint64(25)).To(Equal(total))
Expand All @@ -315,7 +315,7 @@ var _ = Describe("Http reader", func() {
defer ts.Close()
ep, err := url.Parse(ts.URL)
Expect(err).ToNot(HaveOccurred())
r, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil)
r, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt)
Expect(err).ToNot(HaveOccurred())
Expect(uint64(0)).To(Equal(total))
err = r.Close()
Expand All @@ -339,7 +339,7 @@ var _ = Describe("Http reader", func() {
defer ts.Close()
ep, err := url.Parse(ts.URL)
Expect(err).ToNot(HaveOccurred())
r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil)
r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt)
Expect(brokenForQemuImg).To(BeTrue())
Expect(err).ToNot(HaveOccurred())
Expect(uint64(25)).To(Equal(total))
Expand All @@ -359,7 +359,7 @@ var _ = Describe("Http reader", func() {
defer ts.Close()
ep, err := url.Parse(ts.URL)
Expect(err).ToNot(HaveOccurred())
r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil)
r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt)
Expect(brokenForQemuImg).To(BeTrue())
Expect(err).ToNot(HaveOccurred())
Expect(uint64(25)).To(Equal(total))
Expand All @@ -374,7 +374,7 @@ var _ = Describe("Http reader", func() {
defer ts.Close()
ep, err := url.Parse(ts.URL)
Expect(err).ToNot(HaveOccurred())
_, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil)
_, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt)
Expect(err).To(HaveOccurred())
Expect(uint64(0)).To(Equal(total))
Expect("expected status code 200, got 500. Status: 500 Internal Server Error").To(Equal(err.Error()))
Expand All @@ -391,7 +391,7 @@ var _ = Describe("Http reader", func() {
defer ts.Close()
ep, err := url.Parse(ts.URL)
Expect(err).ToNot(HaveOccurred())
r, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", []string{"Extra-Header: 123"}, nil)
r, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", []string{"Extra-Header: 123"}, nil, cdiv1.DataVolumeKubeVirt)
Expect(err).ToNot(HaveOccurred())
Expect(uint64(0)).To(Equal(total))
err = r.Close()
Expand Down