Supporting User Delegation SAS (#259)
* Changes to support new user delegation SAS * Added support for user delegation SAS * Support generation of Directory SAS * Correcting UDK struct and updating SAS & Blob SAS query params * Pinning down old SASVersion * Renaming for SDK consistency, adding tests * Reorganizing for CI * Cleaning up tests * Cleaning up tests due to CI * Adding change to resolve CI issues * Addressing PR comments * Test for sdd * Update sdd test * Fix tests Co-authored-by: Narasimha Kulkarni <63087328+nakulkar-msft@users.noreply.github.com> Co-authored-by: Ze Qian Zhang <zezha@microsoft.com>
This commit is contained in:
Родитель
ce5190c9fe
Коммит
deb21f705e
|
@ -10,21 +10,33 @@ import (
|
|||
// BlobSASSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage container or blob.
|
||||
// For more information, see https://docs.microsoft.com/rest/api/storageservices/constructing-a-service-sas
|
||||
type BlobSASSignatureValues struct {
|
||||
Version string `param:"sv"` // If not specified, this defaults to SASVersion
|
||||
Protocol SASProtocol `param:"spr"` // See the SASProtocol* constants
|
||||
StartTime time.Time `param:"st"` // Not specified if IsZero
|
||||
ExpiryTime time.Time `param:"se"` // Not specified if IsZero
|
||||
SnapshotTime time.Time
|
||||
Permissions string `param:"sp"` // Create by initializing a ContainerSASPermissions or BlobSASPermissions and then call String()
|
||||
IPRange IPRange `param:"sip"`
|
||||
Identifier string `param:"si"`
|
||||
ContainerName string
|
||||
BlobName string // Use "" to create a Container SAS
|
||||
CacheControl string // rscc
|
||||
ContentDisposition string // rscd
|
||||
ContentEncoding string // rsce
|
||||
ContentLanguage string // rscl
|
||||
ContentType string // rsct
|
||||
Version string `param:"sv"` // If not specified, this defaults to SASVersion
|
||||
Protocol SASProtocol `param:"spr"` // See the SASProtocol* constants
|
||||
StartTime time.Time `param:"st"` // Not specified if IsZero
|
||||
ExpiryTime time.Time `param:"se"` // Not specified if IsZero
|
||||
SnapshotTime time.Time
|
||||
Permissions string `param:"sp"` // Create by initializing a ContainerSASPermissions or BlobSASPermissions and then call String()
|
||||
IPRange IPRange `param:"sip"`
|
||||
Identifier string `param:"si"`
|
||||
ContainerName string
|
||||
BlobName string // Use "" to create a Container SAS
|
||||
Directory string // Not nil for a directory SAS (ie sr=d)
|
||||
CacheControl string // rscc
|
||||
ContentDisposition string // rscd
|
||||
ContentEncoding string // rsce
|
||||
ContentLanguage string // rscl
|
||||
ContentType string // rsct
|
||||
BlobVersion string // sr=bv
|
||||
PreauthorizedAgentObjectId string
|
||||
AgentObjectId string
|
||||
CorrelationId string
|
||||
}
|
||||
|
||||
func getDirectoryDepth(path string) string {
|
||||
if path == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(strings.Count(path, "/") + 1)
|
||||
}
|
||||
|
||||
// NewSASQueryParameters uses an account's StorageAccountCredential to sign this signature values to produce
|
||||
|
@ -44,7 +56,7 @@ func (v BlobSASSignatureValues) NewSASQueryParameters(credential StorageAccountC
|
|||
return SASQueryParameters{}, err
|
||||
}
|
||||
v.Permissions = perms.String()
|
||||
} else if v.Version != "" {
|
||||
} else if v.BlobVersion != "" {
|
||||
resource = "bv"
|
||||
//Make sure the permission characters are in the correct order
|
||||
perms := &BlobSASPermissions{}
|
||||
|
@ -52,6 +64,14 @@ func (v BlobSASSignatureValues) NewSASQueryParameters(credential StorageAccountC
|
|||
return SASQueryParameters{}, err
|
||||
}
|
||||
v.Permissions = perms.String()
|
||||
} else if v.Directory != "" {
|
||||
resource = "d"
|
||||
v.BlobName = ""
|
||||
perms := &BlobSASPermissions{}
|
||||
if err := perms.Parse(v.Permissions); err != nil {
|
||||
return SASQueryParameters{}, err
|
||||
}
|
||||
v.Permissions = perms.String()
|
||||
} else if v.BlobName == "" {
|
||||
// Make sure the permission characters are in the correct order
|
||||
perms := &ContainerSASPermissions{}
|
||||
|
@ -88,6 +108,9 @@ func (v BlobSASSignatureValues) NewSASQueryParameters(credential StorageAccountC
|
|||
udkExpiry,
|
||||
udk.SignedService,
|
||||
udk.SignedVersion,
|
||||
v.PreauthorizedAgentObjectId,
|
||||
v.AgentObjectId,
|
||||
v.CorrelationId,
|
||||
}, "\n")
|
||||
}
|
||||
|
||||
|
@ -96,7 +119,7 @@ func (v BlobSASSignatureValues) NewSASQueryParameters(credential StorageAccountC
|
|||
v.Permissions,
|
||||
startTime,
|
||||
expiryTime,
|
||||
getCanonicalName(credential.AccountName(), v.ContainerName, v.BlobName),
|
||||
getCanonicalName(credential.AccountName(), v.ContainerName, v.BlobName, v.Directory),
|
||||
signedIdentifier,
|
||||
v.IPRange.String(),
|
||||
string(v.Protocol),
|
||||
|
@ -123,15 +146,18 @@ func (v BlobSASSignatureValues) NewSASQueryParameters(credential StorageAccountC
|
|||
ipRange: v.IPRange,
|
||||
|
||||
// Container/Blob-specific SAS parameters
|
||||
resource: resource,
|
||||
identifier: v.Identifier,
|
||||
cacheControl: v.CacheControl,
|
||||
contentDisposition: v.ContentDisposition,
|
||||
contentEncoding: v.ContentEncoding,
|
||||
contentLanguage: v.ContentLanguage,
|
||||
contentType: v.ContentType,
|
||||
snapshotTime: v.SnapshotTime,
|
||||
|
||||
resource: resource,
|
||||
identifier: v.Identifier,
|
||||
cacheControl: v.CacheControl,
|
||||
contentDisposition: v.ContentDisposition,
|
||||
contentEncoding: v.ContentEncoding,
|
||||
contentLanguage: v.ContentLanguage,
|
||||
contentType: v.ContentType,
|
||||
snapshotTime: v.SnapshotTime,
|
||||
signedDirectoryDepth: getDirectoryDepth(v.Directory),
|
||||
preauthorizedAgentObjectId: v.PreauthorizedAgentObjectId,
|
||||
agentObjectId: v.AgentObjectId,
|
||||
correlationId: v.CorrelationId,
|
||||
// Calculated SAS signature
|
||||
signature: signature,
|
||||
}
|
||||
|
@ -150,12 +176,14 @@ func (v BlobSASSignatureValues) NewSASQueryParameters(credential StorageAccountC
|
|||
}
|
||||
|
||||
// getCanonicalName computes the canonical name for a container or blob resource for SAS signing.
|
||||
func getCanonicalName(account string, containerName string, blobName string) string {
|
||||
func getCanonicalName(account string, containerName string, blobName string, directoryName string) string {
|
||||
// Container: "/blob/account/containername"
|
||||
// Blob: "/blob/account/containername/blobname"
|
||||
elements := []string{"/blob/", account, "/", containerName}
|
||||
if blobName != "" {
|
||||
elements = append(elements, "/", strings.Replace(blobName, "\\", "/", -1))
|
||||
} else if directoryName != "" {
|
||||
elements = append(elements, "/", directoryName)
|
||||
}
|
||||
return strings.Join(elements, "")
|
||||
}
|
||||
|
@ -244,9 +272,8 @@ func (p *ContainerSASPermissions) Parse(s string) error {
|
|||
|
||||
// The BlobSASPermissions type simplifies creating the permissions string for an Azure Storage blob SAS.
|
||||
// Initialize an instance of this type and then call its String method to set BlobSASSignatureValues's Permissions field.
|
||||
type BlobSASPermissions struct{
|
||||
Read, Add, Create, Write, Delete, DeletePreviousVersion, Tag bool
|
||||
Execute, ModifyOwnership, ModifyPermissions bool // Hierarchical Namespace only
|
||||
type BlobSASPermissions struct {
|
||||
Read, Add, Create, Write, Delete, DeletePreviousVersion, Tag, List, Move, Execute, Ownership, Permissions bool
|
||||
}
|
||||
|
||||
// String produces the SAS permissions string for an Azure Storage blob.
|
||||
|
@ -274,13 +301,19 @@ func (p BlobSASPermissions) String() string {
|
|||
if p.Tag {
|
||||
b.WriteRune('t')
|
||||
}
|
||||
if p.List {
|
||||
b.WriteRune('l')
|
||||
}
|
||||
if p.Move {
|
||||
b.WriteRune('m')
|
||||
}
|
||||
if p.Execute {
|
||||
b.WriteRune('e')
|
||||
}
|
||||
if p.ModifyOwnership {
|
||||
if p.Ownership {
|
||||
b.WriteRune('o')
|
||||
}
|
||||
if p.ModifyPermissions {
|
||||
if p.Permissions {
|
||||
b.WriteRune('p')
|
||||
}
|
||||
return b.String()
|
||||
|
@ -305,12 +338,16 @@ func (p *BlobSASPermissions) Parse(s string) error {
|
|||
p.DeletePreviousVersion = true
|
||||
case 't':
|
||||
p.Tag = true
|
||||
case 'l':
|
||||
p.List = true
|
||||
case 'm':
|
||||
p.Move = true
|
||||
case 'e':
|
||||
p.Execute = true
|
||||
case 'o':
|
||||
p.ModifyOwnership = true
|
||||
p.Ownership = true
|
||||
case 'p':
|
||||
p.ModifyPermissions = true
|
||||
p.Permissions = true
|
||||
default:
|
||||
return fmt.Errorf("invalid permission: '%v'", r)
|
||||
}
|
||||
|
|
|
@ -83,37 +83,48 @@ func parseSASTimeString(val string) (t time.Time, timeFormat string, err error)
|
|||
// This type defines the components used by all Azure Storage resources (Containers, Blobs, Files, & Queues).
|
||||
type SASQueryParameters struct {
|
||||
// All members are immutable or values so copies of this struct are goroutine-safe.
|
||||
version string `param:"sv"`
|
||||
services string `param:"ss"`
|
||||
resourceTypes string `param:"srt"`
|
||||
protocol SASProtocol `param:"spr"`
|
||||
startTime time.Time `param:"st"`
|
||||
expiryTime time.Time `param:"se"`
|
||||
snapshotTime time.Time `param:"snapshot"`
|
||||
ipRange IPRange `param:"sip"`
|
||||
identifier string `param:"si"`
|
||||
resource string `param:"sr"`
|
||||
permissions string `param:"sp"`
|
||||
signature string `param:"sig"`
|
||||
cacheControl string `param:"rscc"`
|
||||
contentDisposition string `param:"rscd"`
|
||||
contentEncoding string `param:"rsce"`
|
||||
contentLanguage string `param:"rscl"`
|
||||
contentType string `param:"rsct"`
|
||||
signedOid string `param:"skoid"`
|
||||
signedTid string `param:"sktid"`
|
||||
signedStart time.Time `param:"skt"`
|
||||
signedExpiry time.Time `param:"ske"`
|
||||
signedService string `param:"sks"`
|
||||
signedVersion string `param:"skv"`
|
||||
|
||||
version string `param:"sv"`
|
||||
services string `param:"ss"`
|
||||
resourceTypes string `param:"srt"`
|
||||
protocol SASProtocol `param:"spr"`
|
||||
startTime time.Time `param:"st"`
|
||||
expiryTime time.Time `param:"se"`
|
||||
snapshotTime time.Time `param:"snapshot"`
|
||||
ipRange IPRange `param:"sip"`
|
||||
identifier string `param:"si"`
|
||||
resource string `param:"sr"`
|
||||
permissions string `param:"sp"`
|
||||
signature string `param:"sig"`
|
||||
cacheControl string `param:"rscc"`
|
||||
contentDisposition string `param:"rscd"`
|
||||
contentEncoding string `param:"rsce"`
|
||||
contentLanguage string `param:"rscl"`
|
||||
contentType string `param:"rsct"`
|
||||
signedOid string `param:"skoid"`
|
||||
signedTid string `param:"sktid"`
|
||||
signedStart time.Time `param:"skt"`
|
||||
signedService string `param:"sks"`
|
||||
signedExpiry time.Time `param:"ske"`
|
||||
signedVersion string `param:"skv"`
|
||||
signedDirectoryDepth string `param:"sdd"`
|
||||
preauthorizedAgentObjectId string `param:"saoid"`
|
||||
agentObjectId string `param:"suoid"`
|
||||
correlationId string `param:"scid"`
|
||||
// private member used for startTime and expiryTime formatting.
|
||||
stTimeFormat string
|
||||
seTimeFormat string
|
||||
}
|
||||
|
||||
func (p *SASQueryParameters) SignedOid() string {
|
||||
return p.signedOid
|
||||
func (p *SASQueryParameters) PreauthorizedAgentObjectId() string {
|
||||
return p.preauthorizedAgentObjectId
|
||||
}
|
||||
|
||||
func (p *SASQueryParameters) AgentObjectId() string {
|
||||
return p.agentObjectId
|
||||
}
|
||||
|
||||
func (p *SASQueryParameters) SignedCorrelationId() string {
|
||||
return p.correlationId
|
||||
}
|
||||
|
||||
func (p *SASQueryParameters) SignedTid() string {
|
||||
|
@ -199,6 +210,10 @@ func (p *SASQueryParameters) ContentType() string {
|
|||
return p.contentType
|
||||
}
|
||||
|
||||
func (p *SASQueryParameters) SignedDirectoryDepth() string {
|
||||
return p.signedDirectoryDepth
|
||||
}
|
||||
|
||||
// IPRange represents a SAS IP range's start IP and (optionally) end IP.
|
||||
type IPRange struct {
|
||||
Start net.IP // Not specified if length = 0
|
||||
|
@ -279,6 +294,14 @@ func newSASQueryParameters(values url.Values, deleteSASParametersFromValues bool
|
|||
p.signedService = val
|
||||
case "skv":
|
||||
p.signedVersion = val
|
||||
case "sdd":
|
||||
p.signedDirectoryDepth = val
|
||||
case "saoid":
|
||||
p.preauthorizedAgentObjectId = val
|
||||
case "suoid":
|
||||
p.agentObjectId = val
|
||||
case "scid":
|
||||
p.correlationId = val
|
||||
default:
|
||||
isSASKey = false // We didn't recognize the query parameter
|
||||
}
|
||||
|
@ -347,6 +370,18 @@ func (p *SASQueryParameters) addToValues(v url.Values) url.Values {
|
|||
if p.contentType != "" {
|
||||
v.Add("rsct", p.contentType)
|
||||
}
|
||||
if p.signedDirectoryDepth != "" {
|
||||
v.Add("sdd", p.signedDirectoryDepth)
|
||||
}
|
||||
if p.preauthorizedAgentObjectId != "" {
|
||||
v.Add("saoid", p.preauthorizedAgentObjectId)
|
||||
}
|
||||
if p.agentObjectId != "" {
|
||||
v.Add("suoid", p.agentObjectId)
|
||||
}
|
||||
if p.correlationId != "" {
|
||||
v.Add("scid", p.correlationId)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
|
|
|
@ -1,32 +1,108 @@
|
|||
package azblob
|
||||
|
||||
// TODO: This test will be addressed, it is failing due to a service change
|
||||
//Creates a container and tests permissions by listing blobs
|
||||
/*func (s *aztestsSuite) TestUserDelegationSASContainer(c *chk.C) {
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/Azure/azure-pipeline-go/pipeline"
|
||||
chk "gopkg.in/check.v1"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func CreateUserDelegationKey(c *chk.C) (containerURL ContainerURL, containerName string, blobURL BlockBlobURL, blobName string, budk UserDelegationCredential, currentTime time.Time, p pipeline.Pipeline) {
|
||||
// Accumulate prerequisite details to create storage etc.
|
||||
bsu := getBSU()
|
||||
containerURL, containerName := getContainerURL(c, bsu)
|
||||
currentTime := time.Now().UTC()
|
||||
containerURL, containerName = getContainerURL(c, bsu)
|
||||
blobURL, blobName = getBlockBlobURL(c, containerURL)
|
||||
currentTime = time.Now().UTC().Add(-10 * time.Second)
|
||||
ocred, err := getOAuthCredential("")
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
// Create pipeline w/ OAuth to handle user delegation key obtaining
|
||||
p := NewPipeline(*ocred, PipelineOptions{})
|
||||
// Create pipeline to handle requests
|
||||
p = NewPipeline(*ocred, PipelineOptions{})
|
||||
|
||||
// Prepare user delegation key
|
||||
bsu = bsu.WithPipeline(p)
|
||||
keyInfo := NewKeyInfo(currentTime, currentTime.Add(48*time.Hour))
|
||||
cudk, err := bsu.GetUserDelegationCredential(ctx, keyInfo, nil, nil)
|
||||
budk, err = bsu.GetUserDelegationCredential(ctx, keyInfo, nil, nil) //MUST have TokenCredential
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
return containerURL, containerName, blobURL, blobName, budk, currentTime, p
|
||||
}
|
||||
|
||||
// Attempting to create User Delegation Key SAS with Incorrect Permissions, should return err
|
||||
func (s *aztestsSuite) TestUserDelegationSASIncorrectPermissions(c *chk.C) {
|
||||
_, containerName, _, blobName, cudk, currentTime, _ := CreateUserDelegationKey(c)
|
||||
// Prepare User Delegation SAS query for Container
|
||||
_, err := BlobSASSignatureValues{
|
||||
Protocol: SASProtocolHTTPS,
|
||||
StartTime: currentTime,
|
||||
ExpiryTime: currentTime.Add(24 * time.Hour),
|
||||
Permissions: "rdq",
|
||||
ContainerName: containerName,
|
||||
}.NewSASQueryParameters(cudk)
|
||||
c.Assert(err, chk.NotNil)
|
||||
|
||||
// Prepare User Delegation SAS query for Blob; returns err due to wrong permission
|
||||
_, err = BlobSASSignatureValues{
|
||||
Protocol: SASProtocolHTTPS,
|
||||
StartTime: currentTime,
|
||||
ExpiryTime: currentTime.Add(24 * time.Hour),
|
||||
Permissions: "rdq",
|
||||
ContainerName: containerName,
|
||||
BlobName: blobName,
|
||||
}.NewSASQueryParameters(cudk)
|
||||
c.Assert(err, chk.NotNil)
|
||||
}
|
||||
|
||||
// Creates a container with no permissions, upload fails due to lack of permissions
|
||||
func (s *aztestsSuite) TestUserDelegationSASContainerNoPermissions(c *chk.C) {
|
||||
containerURL, containerName, _, _, cudk, currentTime, p := CreateUserDelegationKey(c)
|
||||
// Prepare User Delegation SAS query
|
||||
cSAS, err := BlobSASSignatureValues{
|
||||
Protocol: SASProtocolHTTPS,
|
||||
StartTime: currentTime,
|
||||
ExpiryTime: currentTime.Add(24 * time.Hour),
|
||||
Permissions: "racwdl",
|
||||
ContainerName: containerName,
|
||||
}.NewSASQueryParameters(cudk)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
// Create anonymous pipeline
|
||||
p = NewPipeline(NewAnonymousCredential(), PipelineOptions{})
|
||||
|
||||
// Create the container
|
||||
_, err = containerURL.Create(ctx, Metadata{}, PublicAccessNone)
|
||||
defer containerURL.Delete(ctx, ContainerAccessConditions{})
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
// Craft a container URL w/ container UDK SAS
|
||||
cURL := containerURL.URL()
|
||||
cURL.RawQuery += cSAS.Encode()
|
||||
cSASURL := NewContainerURL(cURL, p)
|
||||
|
||||
// Create blob; upload returns err due to lack of permissions
|
||||
bblob := cSASURL.NewBlockBlobURL("test")
|
||||
_, err = bblob.Upload(ctx, strings.NewReader("hello world!"), BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{}, DefaultAccessTier, nil, ClientProvidedKeyOptions{})
|
||||
c.Assert(err, chk.NotNil)
|
||||
}
|
||||
|
||||
// Creates a container with all permissions
|
||||
func (s *aztestsSuite) TestUserDelegationSASContainerAllPermissions(c *chk.C) {
|
||||
containerURL, containerName, _, _, cudk, currentTime, p := CreateUserDelegationKey(c)
|
||||
// Prepare User Delegation SAS query
|
||||
cSAS, err := BlobSASSignatureValues{
|
||||
Protocol: SASProtocolHTTPS,
|
||||
StartTime: currentTime,
|
||||
ExpiryTime: currentTime.Add(24 * time.Hour),
|
||||
Permissions: "racwdxlt",
|
||||
ContainerName: containerName,
|
||||
}.NewSASQueryParameters(cudk)
|
||||
if err != nil {
|
||||
|
@ -74,38 +150,18 @@ package azblob
|
|||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// TODO: This test will be addressed, it is failing due to a service change
|
||||
// Creates a blob, takes a snapshot, downloads from snapshot, and deletes from the snapshot w/ the token
|
||||
/*func (s *aztestsSuite) TestUserDelegationSASBlob(c *chk.C) {
|
||||
// Accumulate prerequisite details to create storage etc.
|
||||
bsu := getBSU()
|
||||
containerURL, containerName := getContainerURL(c, bsu)
|
||||
blobURL, blobName := getBlockBlobURL(c, containerURL)
|
||||
currentTime := time.Now().UTC()
|
||||
ocred, err := getOAuthCredential("")
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
// Create pipeline to handle requests
|
||||
p := NewPipeline(*ocred, PipelineOptions{})
|
||||
|
||||
// Prepare user delegation key
|
||||
bsu = bsu.WithPipeline(p)
|
||||
keyInfo := NewKeyInfo(currentTime, currentTime.Add(48*time.Hour))
|
||||
budk, err := bsu.GetUserDelegationCredential(ctx, keyInfo, nil, nil) //MUST have TokenCredential
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
// Creates a blob with all permissions, takes a snapshot, downloads from snapshot, and deletes from the snapshot w/ the token
|
||||
func (s *aztestsSuite) TestUserDelegationSASBlobAllPermissions(c *chk.C) {
|
||||
containerURL, containerName, blobURL, blobName, budk, currentTime, p := CreateUserDelegationKey(c)
|
||||
|
||||
// Prepare User Delegation SAS query
|
||||
bSAS, err := BlobSASSignatureValues{
|
||||
Protocol: SASProtocolHTTPS,
|
||||
StartTime: currentTime,
|
||||
ExpiryTime: currentTime.Add(24 * time.Hour),
|
||||
Permissions: "rd",
|
||||
Permissions: "racwdxtmeop",
|
||||
ContainerName: containerName,
|
||||
BlobName: blobName,
|
||||
}.NewSASQueryParameters(budk)
|
||||
|
@ -155,4 +211,105 @@ package azblob
|
|||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// Creates User Delegation SAS with saoid and checks if URL is correctly formed
|
||||
func (s *aztestsSuite) TestUserDelegationSaoid(c *chk.C) {
|
||||
_, containerName, blobURL, blobName, budk, currentTime, p := CreateUserDelegationKey(c)
|
||||
saoid := newUUID().String()
|
||||
// Prepare User Delegation SAS query
|
||||
bSAS, err := BlobSASSignatureValues{
|
||||
Protocol: SASProtocolHTTPS,
|
||||
StartTime: currentTime,
|
||||
ExpiryTime: currentTime.Add(24 * time.Hour),
|
||||
Permissions: "rd",
|
||||
ContainerName: containerName,
|
||||
BlobName: blobName,
|
||||
PreauthorizedAgentObjectId: saoid,
|
||||
}.NewSASQueryParameters(budk)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
// Create pipeline
|
||||
p = NewPipeline(NewAnonymousCredential(), PipelineOptions{})
|
||||
|
||||
// Append User Delegation SAS token to URL
|
||||
bSASParts := NewBlobURLParts(blobURL.URL())
|
||||
bSASParts.SAS = bSAS
|
||||
bSASURL := NewBlockBlobURL(bSASParts.URL(), p)
|
||||
|
||||
c.Assert(strings.Contains(bSASURL.blobClient.url.RawQuery, "saoid="+saoid), chk.Equals, true)
|
||||
}
|
||||
|
||||
// Creates User Delegation SAS with suoid and checks if URL is correctly formed
|
||||
func (s *aztestsSuite) TestUserDelegationSuoid(c *chk.C) {
|
||||
_, containerName, blobURL, blobName, budk, currentTime, p := CreateUserDelegationKey(c)
|
||||
suoid := newUUID().String()
|
||||
// Prepare User Delegation SAS query
|
||||
bSAS, err := BlobSASSignatureValues{
|
||||
Protocol: SASProtocolHTTPS,
|
||||
StartTime: currentTime,
|
||||
ExpiryTime: currentTime.Add(24 * time.Hour),
|
||||
Permissions: "rd",
|
||||
ContainerName: containerName,
|
||||
BlobName: blobName,
|
||||
AgentObjectId: suoid,
|
||||
}.NewSASQueryParameters(budk)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
// Create pipeline
|
||||
p = NewPipeline(NewAnonymousCredential(), PipelineOptions{})
|
||||
|
||||
// Append User Delegation SAS token to URL
|
||||
bSASParts := NewBlobURLParts(blobURL.URL())
|
||||
bSASParts.SAS = bSAS
|
||||
bSASURL := NewBlockBlobURL(bSASParts.URL(), p)
|
||||
|
||||
c.Assert(strings.Contains(bSASURL.blobClient.url.RawQuery, "suoid="+suoid), chk.Equals, true)
|
||||
}
|
||||
|
||||
// Creates User Delegation SAS with correlation id and checks if URL is correctly formed
|
||||
func (s *aztestsSuite) TestUserDelegationCid(c *chk.C) {
|
||||
_, containerName, blobURL, blobName, budk, currentTime, p := CreateUserDelegationKey(c)
|
||||
cid := newUUID().String()
|
||||
// Prepare User Delegation SAS query
|
||||
bSAS, err := BlobSASSignatureValues{
|
||||
Protocol: SASProtocolHTTPS,
|
||||
StartTime: currentTime,
|
||||
ExpiryTime: currentTime.Add(24 * time.Hour),
|
||||
Permissions: "rd",
|
||||
ContainerName: containerName,
|
||||
BlobName: blobName,
|
||||
CorrelationId: cid,
|
||||
}.NewSASQueryParameters(budk)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
// Create pipeline
|
||||
p = NewPipeline(NewAnonymousCredential(), PipelineOptions{})
|
||||
|
||||
// Append User Delegation SAS token to URL
|
||||
bSASParts := NewBlobURLParts(blobURL.URL())
|
||||
bSASParts.SAS = bSAS
|
||||
bSASURL := NewBlockBlobURL(bSASParts.URL(), p)
|
||||
|
||||
c.Assert(strings.Contains(bSASURL.blobClient.url.RawQuery, "cid="+cid), chk.Equals, true)
|
||||
}
|
||||
|
||||
func (s *aztestsSuite) TestParseSASQueryParams(c *chk.C) {
|
||||
const blobURL = "https://myaccount.blob.core.windows.net/mycontainer/testfile?sp=r&st=2021-03-19T03:48:02Z&se=2021-03-19T11:48:02Z&spr=https&sv=2020-02-10&sr=d&sdd=10&sig=invalidsignature"
|
||||
|
||||
testURL, _ := url.Parse(blobURL)
|
||||
|
||||
bURLParts := NewBlobURLParts(*testURL)
|
||||
sas := bURLParts.SAS
|
||||
|
||||
c.Assert(sas, chk.NotNil)
|
||||
c.Assert(sas.resource, chk.Equals, "d")
|
||||
c.Assert(sas.SignedDirectoryDepth(), chk.Equals, "10")
|
||||
c.Assert(sas.protocol, chk.Equals, SASProtocolHTTPS)
|
||||
}
|
||||
|
|
|
@ -7777,7 +7777,7 @@ func init() {
|
|||
}
|
||||
|
||||
const (
|
||||
rfc3339Format = "2006-01-02T15:04:05.0000000Z07:00"
|
||||
rfc3339Format = "2006-01-02T15:04:05Z"
|
||||
)
|
||||
|
||||
// used to convert times from UTC to GMT before sending across the wire
|
||||
|
|
Загрузка…
Ссылка в новой задаче