2016-07-07 02:07:55 +03:00
|
|
|
package download
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"math/rand"
|
2019-07-25 03:57:36 +03:00
|
|
|
"net/http"
|
2016-07-07 02:07:55 +03:00
|
|
|
"os"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/Azure/azure-sdk-for-go/storage"
|
2016-08-01 23:44:25 +03:00
|
|
|
"github.com/Azure/custom-script-extension-linux/pkg/blobutil"
|
2023-01-25 01:48:48 +03:00
|
|
|
"github.com/go-kit/kit/log"
|
2016-07-07 02:07:55 +03:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
2023-01-25 01:48:48 +03:00
|
|
|
var (
|
|
|
|
testctx = log.NewContext(log.NewNopLogger())
|
|
|
|
)
|
|
|
|
|
2016-07-07 02:07:55 +03:00
|
|
|
func Test_blobDownload_validateInputs(t *testing.T) {
|
|
|
|
type sas interface {
|
|
|
|
getURL() (string, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := NewBlobDownload("", "", blobutil.AzureBlobRef{}).GetRequest()
|
|
|
|
require.NotNil(t, err)
|
|
|
|
require.Contains(t, err.Error(), "failed to initialize azure storage client")
|
|
|
|
require.Contains(t, err.Error(), "account name required")
|
|
|
|
|
|
|
|
_, err = NewBlobDownload("account", "", blobutil.AzureBlobRef{}).GetRequest()
|
|
|
|
require.NotNil(t, err)
|
|
|
|
require.Contains(t, err.Error(), "failed to initialize azure storage client")
|
|
|
|
require.Contains(t, err.Error(), "account key required")
|
|
|
|
|
|
|
|
_, err = NewBlobDownload("account", "Zm9vCg==", blobutil.AzureBlobRef{}).GetRequest()
|
|
|
|
require.NotNil(t, err)
|
|
|
|
require.Contains(t, err.Error(), "failed to initialize azure storage client")
|
|
|
|
|
|
|
|
_, err = NewBlobDownload("account", "Zm9vCg==", blobutil.AzureBlobRef{
|
|
|
|
StorageBase: storage.DefaultBaseURL,
|
|
|
|
}).GetRequest()
|
|
|
|
require.Nil(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_blobDownload_getURL(t *testing.T) {
|
|
|
|
type sas interface {
|
|
|
|
getURL() (string, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
d := NewBlobDownload("account", "Zm9vCg==", blobutil.AzureBlobRef{
|
|
|
|
StorageBase: "test.core.windows.net",
|
|
|
|
Container: "",
|
|
|
|
Blob: "blob.txt",
|
|
|
|
})
|
|
|
|
|
|
|
|
v, ok := d.(blobDownload)
|
|
|
|
require.True(t, ok)
|
|
|
|
|
|
|
|
url, err := v.getURL()
|
|
|
|
require.Nil(t, err)
|
|
|
|
require.Contains(t, url, "https://", "missing https scheme")
|
|
|
|
require.Contains(t, url, "/account.blob.test.core.windows.net/", "missing/wrong host")
|
|
|
|
require.Contains(t, url, "/$root/", "missing container in url")
|
|
|
|
require.Contains(t, url, "/blob.txt", "missing blob name in url")
|
|
|
|
for _, v := range []string{"sig", "se", "sr", "sp", "sv"} { // SAS query parameters
|
|
|
|
require.Contains(t, url, v+"=", "missing SAS query '%s' in url", v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_blobDownload_fails_badCreds(t *testing.T) {
|
2016-10-11 21:19:16 +03:00
|
|
|
d := NewBlobDownload("example", "Zm9vCg==", blobutil.AzureBlobRef{
|
2016-07-07 02:07:55 +03:00
|
|
|
StorageBase: storage.DefaultBaseURL,
|
|
|
|
Blob: "fooBlob.txt",
|
|
|
|
Container: "foocontainer",
|
|
|
|
})
|
|
|
|
|
2023-01-25 01:48:48 +03:00
|
|
|
status, _, err := Download(testctx, d)
|
2016-07-07 02:07:55 +03:00
|
|
|
require.NotNil(t, err)
|
2023-01-25 01:48:48 +03:00
|
|
|
require.Contains(t, err.Error(), "Please verify the machine has network connectivity")
|
|
|
|
require.Contains(t, err.Error(), "403")
|
2019-07-25 03:57:36 +03:00
|
|
|
require.Equal(t, status, http.StatusForbidden)
|
2016-07-07 02:07:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func Test_blobDownload_fails_urlNotFound(t *testing.T) {
|
|
|
|
d := NewBlobDownload("accountname", "Zm9vCg==", blobutil.AzureBlobRef{
|
|
|
|
StorageBase: ".example.com",
|
|
|
|
Blob: "fooBlob.txt",
|
|
|
|
Container: "foocontainer",
|
|
|
|
})
|
|
|
|
|
2023-01-25 01:48:48 +03:00
|
|
|
_, _, err := Download(testctx, d)
|
2016-07-07 02:07:55 +03:00
|
|
|
require.NotNil(t, err)
|
|
|
|
require.Contains(t, err.Error(), "http request failed:")
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_blobDownload_actualBlob(t *testing.T) {
|
|
|
|
acct := os.Getenv("AZURE_STORAGE_ACCOUNT")
|
2016-07-27 23:44:00 +03:00
|
|
|
key := os.Getenv("AZURE_STORAGE_ACCESS_KEY")
|
2016-07-07 02:07:55 +03:00
|
|
|
if acct == "" || key == "" {
|
2016-07-27 23:44:00 +03:00
|
|
|
t.Skipf("Skipping: AZURE_STORAGE_ACCOUNT or AZURE_STORAGE_ACCESS_KEY not specified to run this test")
|
2016-07-07 02:07:55 +03:00
|
|
|
}
|
|
|
|
base := storage.DefaultBaseURL
|
|
|
|
|
|
|
|
// Create a blob first
|
|
|
|
cl, err := storage.NewClient(acct, key, base, storage.DefaultAPIVersion, true)
|
|
|
|
require.Nil(t, err)
|
|
|
|
bs := cl.GetBlobService()
|
|
|
|
|
|
|
|
var (
|
|
|
|
n = 1024 * 64
|
|
|
|
name = "blob.txt"
|
|
|
|
container = fmt.Sprintf("custom-script-test-%d", rand.New(rand.NewSource(time.Now().UnixNano())).Int63())
|
|
|
|
chunk = make([]byte, n)
|
|
|
|
)
|
|
|
|
_, err = bs.DeleteContainerIfExists(container)
|
|
|
|
require.Nil(t, err)
|
|
|
|
_, err = bs.CreateContainerIfNotExists(container, storage.ContainerAccessTypePrivate)
|
|
|
|
require.Nil(t, err)
|
|
|
|
defer bs.DeleteContainer(container)
|
|
|
|
require.Nil(t, bs.PutAppendBlob(container, name, nil))
|
|
|
|
rand.Read(chunk)
|
|
|
|
require.Nil(t, bs.AppendBlock(container, name, chunk, nil))
|
|
|
|
|
|
|
|
// Get the blob via downloader
|
|
|
|
d := NewBlobDownload(acct, key, blobutil.AzureBlobRef{
|
|
|
|
Container: container,
|
|
|
|
Blob: name,
|
|
|
|
StorageBase: base,
|
|
|
|
})
|
2023-01-25 01:48:48 +03:00
|
|
|
_, body, err := Download(testctx, d)
|
2016-07-07 02:07:55 +03:00
|
|
|
require.Nil(t, err)
|
|
|
|
defer body.Close()
|
|
|
|
b, err := ioutil.ReadAll(body)
|
|
|
|
require.Nil(t, err)
|
|
|
|
require.EqualValues(t, chunk, b, "retrieved body is different body=%d chunk=%d", len(b), len(chunk))
|
|
|
|
}
|
2023-01-25 01:48:48 +03:00
|
|
|
|
|
|
|
func Test_blobDownload_fails_actualBlob404(t *testing.T) {
|
|
|
|
acct := os.Getenv("AZURE_STORAGE_ACCOUNT")
|
|
|
|
key := os.Getenv("AZURE_STORAGE_ACCESS_KEY")
|
|
|
|
if acct == "" || key == "" {
|
|
|
|
t.Skipf("Skipping: AZURE_STORAGE_ACCOUNT or AZURE_STORAGE_ACCESS_KEY not specified to run this test")
|
|
|
|
}
|
|
|
|
base := storage.DefaultBaseURL
|
|
|
|
|
|
|
|
blobName := "<BLOB THAT DOESN'T EXIST>"
|
|
|
|
containerName := "<CONTAINER NAME>"
|
|
|
|
|
|
|
|
// Get the blob via downloader
|
|
|
|
d := NewBlobDownload(acct, key, blobutil.AzureBlobRef{
|
|
|
|
Container: containerName,
|
|
|
|
Blob: blobName,
|
|
|
|
StorageBase: base,
|
|
|
|
})
|
|
|
|
code, _, err := Download(testctx, d)
|
|
|
|
require.NotNil(t, err)
|
|
|
|
require.Equal(t, code, http.StatusNotFound)
|
|
|
|
require.Contains(t, err.Error(), "because it does not exist")
|
|
|
|
require.Contains(t, err.Error(), "Not Found")
|
|
|
|
require.Contains(t, err.Error(), "Service request ID")
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_blobDownload_fails_actualBlob409(t *testing.T) {
|
|
|
|
// before running this test, go to your storage account on portal > Configuration and disable Blob public access
|
|
|
|
acct := os.Getenv("AZURE_STORAGE_ACCOUNT")
|
|
|
|
key := os.Getenv("AZURE_STORAGE_ACCESS_KEY")
|
|
|
|
if acct == "" || key == "" {
|
|
|
|
t.Skipf("Skipping: AZURE_STORAGE_ACCOUNT or AZURE_STORAGE_ACCESS_KEY not specified to run this test")
|
|
|
|
}
|
|
|
|
base := storage.DefaultBaseURL
|
|
|
|
|
|
|
|
blobName := "<BLOB NAME>"
|
|
|
|
containerName := "<CONTAINER NAME>"
|
|
|
|
|
|
|
|
// Get the blob via downloader
|
|
|
|
d := NewBlobDownload(acct, key, blobutil.AzureBlobRef{
|
|
|
|
Container: containerName,
|
|
|
|
Blob: blobName,
|
|
|
|
StorageBase: base,
|
|
|
|
})
|
|
|
|
code, _, err := Download(testctx, d)
|
|
|
|
require.NotNil(t, err)
|
|
|
|
require.Equal(t, code, http.StatusConflict)
|
|
|
|
require.Contains(t, err.Error(), "Please verify the machine has network connectivity")
|
|
|
|
require.Contains(t, err.Error(), "Public access is not permitted on this storage account")
|
|
|
|
require.Contains(t, err.Error(), "Service request ID")
|
|
|
|
}
|