mirror of
https://github.com/restic/restic.git
synced 2024-09-10 05:10:32 +02:00
61cb1cc6f8
This includes github.com/kurin/blazer 0.2.0, which resolves #1291
260 lines
9.8 KiB
Go
260 lines
9.8 KiB
Go
package storage
|
|
|
|
// Copyright 2017 Microsoft Corporation
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"net/http"
|
|
|
|
chk "gopkg.in/check.v1"
|
|
)
|
|
|
|
type AuthorizationSuite struct{}
|
|
|
|
var _ = chk.Suite(&AuthorizationSuite{})
|
|
|
|
func (a *AuthorizationSuite) Test_addAuthorizationHeader(c *chk.C) {
|
|
cli, err := NewBasicClient(dummyStorageAccount, dummyMiniStorageKey)
|
|
c.Assert(err, chk.IsNil)
|
|
cli.UseSharedKeyLite = true
|
|
tableCli := cli.GetTableService()
|
|
|
|
headers := map[string]string{
|
|
"Accept-Charset": "UTF-8",
|
|
headerContentType: "application/json",
|
|
headerXmsDate: "Wed, 23 Sep 2015 16:40:05 GMT",
|
|
headerContentLength: "0",
|
|
headerXmsVersion: "2015-02-21",
|
|
"Accept": "application/json;odata=nometadata",
|
|
}
|
|
url := "https://golangrocksonazure.table.core.windows.net/tquery()"
|
|
headers, err = tableCli.client.addAuthorizationHeader("", url, headers, tableCli.auth)
|
|
c.Assert(err, chk.IsNil)
|
|
|
|
c.Assert(headers[headerAuthorization], chk.Equals, "SharedKeyLite golangrocksonazure:NusXSFXAvHqr6EQNXnZZ50CvU1sX0iP/FFDHehnixLc=")
|
|
}
|
|
|
|
func (a *AuthorizationSuite) Test_getSharedKey(c *chk.C) {
|
|
// Shared Key Lite for Tables
|
|
cli, err := NewBasicClient(dummyStorageAccount, dummyMiniStorageKey)
|
|
c.Assert(err, chk.IsNil)
|
|
|
|
headers := map[string]string{
|
|
"Accept-Charset": "UTF-8",
|
|
headerContentType: "application/json",
|
|
headerXmsDate: "Wed, 23 Sep 2015 16:40:05 GMT",
|
|
headerContentLength: "0",
|
|
headerXmsVersion: "2015-02-21",
|
|
"Accept": "application/json;odata=nometadata",
|
|
}
|
|
url := "https://golangrocksonazure.table.core.windows.net/tquery()"
|
|
|
|
key, err := cli.getSharedKey("", url, headers, sharedKeyLiteForTable)
|
|
c.Assert(err, chk.IsNil)
|
|
c.Assert(key, chk.Equals, "SharedKeyLite golangrocksonazure:NusXSFXAvHqr6EQNXnZZ50CvU1sX0iP/FFDHehnixLc=")
|
|
}
|
|
|
|
func (a *AuthorizationSuite) Test_buildCanonicalizedResource(c *chk.C) {
|
|
cli, err := NewBasicClient(dummyStorageAccount, dummyMiniStorageKey)
|
|
c.Assert(err, chk.IsNil)
|
|
|
|
type test struct {
|
|
url string
|
|
auth authentication
|
|
expected string
|
|
sas bool
|
|
}
|
|
tests := []test{
|
|
// Shared Key
|
|
{"https://golangrocksonazure.blob.core.windows.net/path?a=b&c=d", sharedKey, "/golangrocksonazure/path\na:b\nc:d", false},
|
|
{"https://golangrocksonazure.blob.core.windows.net/?comp=list", sharedKey, "/golangrocksonazure/\ncomp:list", false},
|
|
{"https://golangrocksonazure.blob.core.windows.net/cnt/blob", sharedKey, "/golangrocksonazure/cnt/blob", false},
|
|
{"https://golangrocksonazure.blob.core.windows.net/cnt/bl ob", sharedKey, "/golangrocksonazure/cnt/bl%20ob", false},
|
|
{"https://golangrocksonazure.blob.core.windows.net/c nt/blob", sharedKey, "/golangrocksonazure/c%20nt/blob", false},
|
|
{"https://golangrocksonazure.blob.core.windows.net/cnt/blob%3F%23%5B%5D%21$&%27%28%29%2A blob", sharedKey, "/golangrocksonazure/cnt/blob%3F%23%5B%5D%21$&%27%28%29%2A%20blob", false},
|
|
{"https://golangrocksonazure.blob.core.windows.net/cnt/blob-._~:,@;+=blob", sharedKey, "/golangrocksonazure/cnt/blob-._~:,@;+=blob", false},
|
|
{"https://golangrocksonazure.blob.core.windows.net/c nt/blob-._~:%3F%23%5B%5D@%21$&%27%28%29%2A,;+=/blob", sharedKey, "/golangrocksonazure/c%20nt/blob-._~:%3F%23%5B%5D@%21$&%27%28%29%2A,;+=/blob", false},
|
|
// Shared Key Lite for Table
|
|
{"https://golangrocksonazure.table.core.windows.net/mytable", sharedKeyLiteForTable, "/golangrocksonazure/mytable", false},
|
|
{"https://golangrocksonazure.table.core.windows.net/mytable?comp=acl", sharedKeyLiteForTable, "/golangrocksonazure/mytable?comp=acl", false},
|
|
{"https://golangrocksonazure.table.core.windows.net/mytable?comp=acl&timeout=10", sharedKeyForTable, "/golangrocksonazure/mytable?comp=acl", false},
|
|
{"https://golangrocksonazure.table.core.windows.net/mytable(PartitionKey='pkey',RowKey='rowkey%3D')", sharedKeyForTable, "/golangrocksonazure/mytable(PartitionKey='pkey',RowKey='rowkey%3D')", false},
|
|
// Canonicalized Resource with SAS
|
|
{"https://golangrocksonazure.blob.core.windows.net/cnt/blob", sharedKey, "/golangrocksonazure/cnt/blob", true},
|
|
}
|
|
|
|
for _, t := range tests {
|
|
out, err := cli.buildCanonicalizedResource(t.url, t.auth, t.sas)
|
|
c.Assert(err, chk.IsNil)
|
|
c.Assert(out, chk.Equals, t.expected)
|
|
}
|
|
|
|
eCli, err := NewEmulatorClient()
|
|
c.Assert(err, chk.IsNil)
|
|
eTests := []test{
|
|
{"http://127.0.0.1:10000/devstoreaccount1/cnt/blob", sharedKey, "/devstoreaccount1/cnt/blob", true},
|
|
{"http://127.0.0.1:10000/devstoreaccount1/cnt/blob", sharedKey, "/devstoreaccount1/devstoreaccount1/cnt/blob", false},
|
|
}
|
|
for _, t := range eTests {
|
|
out, err := eCli.buildCanonicalizedResource(t.url, t.auth, t.sas)
|
|
c.Assert(err, chk.IsNil)
|
|
c.Assert(out, chk.Equals, t.expected)
|
|
}
|
|
}
|
|
|
|
func (a *AuthorizationSuite) Test_buildCanonicalizedString(c *chk.C) {
|
|
var tests = []struct {
|
|
verb string
|
|
headers map[string]string
|
|
canonicalizedResource string
|
|
auth authentication
|
|
out string
|
|
}{
|
|
{
|
|
// Shared Key
|
|
verb: http.MethodGet,
|
|
headers: map[string]string{
|
|
headerXmsDate: "Sun, 11 Oct 2009 21:49:13 GMT",
|
|
headerXmsVersion: "2009-09-19",
|
|
},
|
|
canonicalizedResource: "/myaccount/ mycontainer\ncomp:metadata\nrestype:container\ntimeout:20",
|
|
auth: sharedKey,
|
|
out: "GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Sun, 11 Oct 2009 21:49:13 GMT\nx-ms-version:2009-09-19\n/myaccount/ mycontainer\ncomp:metadata\nrestype:container\ntimeout:20",
|
|
},
|
|
{
|
|
// Shared Key for Tables
|
|
verb: http.MethodPut,
|
|
headers: map[string]string{
|
|
headerContentType: "text/plain; charset=UTF-8",
|
|
headerDate: "Sun, 11 Oct 2009 19:52:39 GMT",
|
|
},
|
|
canonicalizedResource: "/testaccount1/Tables",
|
|
auth: sharedKeyForTable,
|
|
out: "PUT\n\ntext/plain; charset=UTF-8\nSun, 11 Oct 2009 19:52:39 GMT\n/testaccount1/Tables",
|
|
},
|
|
{
|
|
// Shared Key Lite
|
|
verb: http.MethodPut,
|
|
headers: map[string]string{
|
|
headerContentType: "text/plain; charset=UTF-8",
|
|
headerXmsDate: "Sun, 20 Sep 2009 20:36:40 GMT",
|
|
"x-ms-meta-m1": "v1",
|
|
"x-ms-meta-m2": "v2",
|
|
},
|
|
canonicalizedResource: "/testaccount1/mycontainer/hello.txt",
|
|
auth: sharedKeyLite,
|
|
out: "PUT\n\ntext/plain; charset=UTF-8\n\nx-ms-date:Sun, 20 Sep 2009 20:36:40 GMT\nx-ms-meta-m1:v1\nx-ms-meta-m2:v2\n/testaccount1/mycontainer/hello.txt",
|
|
},
|
|
{
|
|
// Shared Key Lite for Tables
|
|
verb: "",
|
|
headers: map[string]string{
|
|
headerDate: "Sun, 11 Oct 2009 19:52:39 GMT",
|
|
},
|
|
canonicalizedResource: "/testaccount1/Tables",
|
|
auth: sharedKeyLiteForTable,
|
|
out: "Sun, 11 Oct 2009 19:52:39 GMT\n/testaccount1/Tables",
|
|
},
|
|
}
|
|
|
|
for _, t := range tests {
|
|
canonicalizedString, err := buildCanonicalizedString(t.verb, t.headers, t.canonicalizedResource, t.auth)
|
|
c.Assert(err, chk.IsNil)
|
|
c.Assert(canonicalizedString, chk.Equals, t.out)
|
|
}
|
|
}
|
|
|
|
func (a *AuthorizationSuite) Test_buildCanonicalizedHeader(c *chk.C) {
|
|
type test struct {
|
|
headers map[string]string
|
|
expected string
|
|
}
|
|
tests := []test{
|
|
{map[string]string{},
|
|
""},
|
|
{map[string]string{
|
|
"x-ms-lol": "rofl"},
|
|
"x-ms-lol:rofl"},
|
|
{map[string]string{
|
|
"lol:": "rofl"},
|
|
""},
|
|
{map[string]string{
|
|
"lol:": "rofl",
|
|
"x-ms-lol": "rofl"},
|
|
"x-ms-lol:rofl"},
|
|
{map[string]string{
|
|
"x-ms-version": "9999-99-99",
|
|
"x-ms-blob-type": "BlockBlob"},
|
|
"x-ms-blob-type:BlockBlob\nx-ms-version:9999-99-99"}}
|
|
|
|
for _, i := range tests {
|
|
c.Assert(buildCanonicalizedHeader(i.headers), chk.Equals, i.expected)
|
|
}
|
|
}
|
|
|
|
func (a *AuthorizationSuite) Test_createAuthorizationHeader(c *chk.C) {
|
|
cli, err := NewBasicClient(dummyStorageAccount, base64.StdEncoding.EncodeToString([]byte("bar")))
|
|
c.Assert(err, chk.IsNil)
|
|
|
|
canonicalizedString := `foobarzoo`
|
|
|
|
c.Assert(cli.createAuthorizationHeader(canonicalizedString, sharedKey),
|
|
chk.Equals, `SharedKey golangrocksonazure:h5U0ATVX6SpbFX1H6GNuxIMeXXCILLoIvhflPtuQZ30=`)
|
|
c.Assert(cli.createAuthorizationHeader(canonicalizedString, sharedKeyLite),
|
|
chk.Equals, `SharedKeyLite golangrocksonazure:h5U0ATVX6SpbFX1H6GNuxIMeXXCILLoIvhflPtuQZ30=`)
|
|
}
|
|
|
|
func (a *AuthorizationSuite) Test_allSharedKeys(c *chk.C) {
|
|
cli := getBasicClient(c)
|
|
rec := cli.appendRecorder(c)
|
|
defer rec.Stop()
|
|
|
|
blobCli := cli.GetBlobService()
|
|
tableCli := cli.GetTableService()
|
|
|
|
cnt1 := blobCli.GetContainerReference(containerName(c, "1"))
|
|
cnt2 := blobCli.GetContainerReference(containerName(c, "2"))
|
|
|
|
// Shared Key
|
|
c.Assert(blobCli.auth, chk.Equals, sharedKey)
|
|
c.Assert(cnt1.Create(nil), chk.IsNil)
|
|
c.Assert(cnt1.Delete(nil), chk.IsNil)
|
|
|
|
// Shared Key for Tables
|
|
c.Assert(tableCli.auth, chk.Equals, sharedKeyForTable)
|
|
table1 := tableCli.GetTableReference(tableName(c, "1"))
|
|
c.Assert(table1.tsc.auth, chk.Equals, sharedKeyForTable)
|
|
c.Assert(table1.Create(30, EmptyPayload, nil), chk.IsNil)
|
|
c.Assert(table1.Delete(30, nil), chk.IsNil)
|
|
|
|
// Change to Lite
|
|
cli.UseSharedKeyLite = true
|
|
blobCli = cli.GetBlobService()
|
|
tableCli = cli.GetTableService()
|
|
|
|
// Shared Key Lite
|
|
c.Assert(blobCli.auth, chk.Equals, sharedKeyLite)
|
|
c.Assert(cnt2.Create(nil), chk.IsNil)
|
|
c.Assert(cnt2.Delete(nil), chk.IsNil)
|
|
|
|
// Shared Key Lite for Tables
|
|
tableCli = cli.GetTableService()
|
|
c.Assert(tableCli.auth, chk.Equals, sharedKeyLiteForTable)
|
|
table2 := tableCli.GetTableReference(tableName(c, "2"))
|
|
c.Assert(table2.tsc.auth, chk.Equals, sharedKeyLiteForTable)
|
|
c.Assert(table2.Create(30, EmptyPayload, nil), chk.IsNil)
|
|
c.Assert(table2.Delete(30, nil), chk.IsNil)
|
|
}
|