1package azblob_test
2
3import (
4	"bytes"
5	"github.com/Azure/azure-storage-blob-go/azblob"
6	chk "gopkg.in/check.v1"
7	"strings"
8	"time"
9)
10
11func (s *aztestsSuite) TestSnapshotSAS(c *chk.C) {
12	//Generate URLs ----------------------------------------------------------------------------------------------------
13	bsu := getBSU()
14	containerURL, containerName := getContainerURL(c, bsu)
15	blobURL, blobName := getBlockBlobURL(c, containerURL)
16
17	_, err := containerURL.Create(ctx, azblob.Metadata{}, azblob.PublicAccessNone)
18	defer containerURL.Delete(ctx, azblob.ContainerAccessConditions{})
19	if err != nil {
20		c.Fatal(err)
21	}
22
23	//Create file in container, download from snapshot to test. --------------------------------------------------------
24	burl := containerURL.NewBlockBlobURL(blobName)
25	data := "Hello world!"
26
27	_, err = burl.Upload(ctx, strings.NewReader(data), azblob.BlobHTTPHeaders{ContentType: "text/plain"}, azblob.Metadata{}, azblob.BlobAccessConditions{})
28	if err != nil {
29		c.Fatal(err)
30	}
31
32	//Create a snapshot & URL
33	createSnapshot, err := burl.CreateSnapshot(ctx, azblob.Metadata{}, azblob.BlobAccessConditions{})
34	if err != nil {
35		c.Fatal(err)
36	}
37
38	//Format snapshot time
39	snapTime, err := time.Parse(azblob.SnapshotTimeFormat, createSnapshot.Snapshot())
40	if err != nil {
41		c.Fatal(err)
42	}
43
44	//Get credentials & current time
45	currentTime := time.Now().UTC()
46	credential, err := getGenericCredential("")
47	if err != nil {
48		c.Fatal("Invalid credential")
49	}
50
51	//Create SAS query
52	snapSASQueryParams, err := azblob.BlobSASSignatureValues{
53		StartTime:     currentTime,
54		ExpiryTime:    currentTime.Add(48 * time.Hour),
55		SnapshotTime:  snapTime,
56		Permissions:   "racwd",
57		ContainerName: containerName,
58		BlobName:      blobName,
59		Protocol:      azblob.SASProtocolHTTPS,
60	}.NewSASQueryParameters(credential)
61	if err != nil {
62		c.Fatal(err)
63	}
64
65	//Attach SAS query to block blob URL
66	p := azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{})
67	snapParts := azblob.NewBlobURLParts(blobURL.URL())
68	snapParts.SAS = snapSASQueryParams
69	sburl := azblob.NewBlockBlobURL(snapParts.URL(), p)
70
71	//Test the snapshot
72	downloadResponse, err := sburl.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
73	if err != nil {
74		c.Fatal(err)
75	}
76
77	downloadedData := &bytes.Buffer{}
78	reader := downloadResponse.Body(azblob.RetryReaderOptions{})
79	downloadedData.ReadFrom(reader)
80	reader.Close()
81
82	c.Assert(data, chk.Equals, downloadedData.String())
83
84	//Try to delete snapshot -------------------------------------------------------------------------------------------
85	_, err = sburl.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
86	if err != nil { //This shouldn't fail.
87		c.Fatal(err)
88	}
89
90	//Create a normal blob and attempt to use the snapshot SAS against it (assuming failure) ---------------------------
91	//If this succeeds, it means a normal SAS token was created.
92
93	fsburl := containerURL.NewBlockBlobURL("failsnap")
94	_, err = fsburl.Upload(ctx, strings.NewReader(data), azblob.BlobHTTPHeaders{ContentType: "text/plain"}, azblob.Metadata{}, azblob.BlobAccessConditions{})
95	if err != nil {
96		c.Fatal(err) //should succeed to create the blob via normal auth means
97	}
98
99	fsburlparts := azblob.NewBlobURLParts(fsburl.URL())
100	fsburlparts.SAS = snapSASQueryParams
101	fsburl = azblob.NewBlockBlobURL(fsburlparts.URL(), p) //re-use fsburl as we don't need the sharedkey version anymore
102
103	resp, err := fsburl.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
104	if err == nil {
105		c.Fatal(resp) //This SHOULD fail. Otherwise we have a normal SAS token...
106	}
107}
108