...

Source file src/github.com/Azure/azure-sdk-for-go/storage/queuesasuri.go

Documentation: github.com/Azure/azure-sdk-for-go/storage

     1  package storage
     2  
     3  // Copyright (c) Microsoft Corporation. All rights reserved.
     4  // Licensed under the MIT License. See License.txt in the project root for license information.
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"net/url"
    10  	"strings"
    11  	"time"
    12  )
    13  
    14  // QueueSASOptions are options to construct a blob SAS
    15  // URI.
    16  // See https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas
    17  type QueueSASOptions struct {
    18  	QueueSASPermissions
    19  	SASOptions
    20  }
    21  
    22  // QueueSASPermissions includes the available permissions for
    23  // a queue SAS URI.
    24  type QueueSASPermissions struct {
    25  	Read    bool
    26  	Add     bool
    27  	Update  bool
    28  	Process bool
    29  }
    30  
    31  func (q QueueSASPermissions) buildString() string {
    32  	permissions := ""
    33  
    34  	if q.Read {
    35  		permissions += "r"
    36  	}
    37  	if q.Add {
    38  		permissions += "a"
    39  	}
    40  	if q.Update {
    41  		permissions += "u"
    42  	}
    43  	if q.Process {
    44  		permissions += "p"
    45  	}
    46  	return permissions
    47  }
    48  
    49  // GetSASURI creates an URL to the specified queue which contains the Shared
    50  // Access Signature with specified permissions and expiration time.
    51  //
    52  // See https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas
    53  func (q *Queue) GetSASURI(options QueueSASOptions) (string, error) {
    54  	canonicalizedResource, err := q.qsc.client.buildCanonicalizedResource(q.buildPath(), q.qsc.auth, true)
    55  	if err != nil {
    56  		return "", err
    57  	}
    58  
    59  	// "The canonicalizedresouce portion of the string is a canonical path to the signed resource.
    60  	// It must include the service name (blob, table, queue or file) for version 2015-02-21 or
    61  	// later, the storage account name, and the resource name, and must be URL-decoded.
    62  	// -- https://msdn.microsoft.com/en-us/library/azure/dn140255.aspx
    63  	// We need to replace + with %2b first to avoid being treated as a space (which is correct for query strings, but not the path component).
    64  	canonicalizedResource = strings.Replace(canonicalizedResource, "+", "%2b", -1)
    65  	canonicalizedResource, err = url.QueryUnescape(canonicalizedResource)
    66  	if err != nil {
    67  		return "", err
    68  	}
    69  
    70  	signedStart := ""
    71  	if options.Start != (time.Time{}) {
    72  		signedStart = options.Start.UTC().Format(time.RFC3339)
    73  	}
    74  	signedExpiry := options.Expiry.UTC().Format(time.RFC3339)
    75  
    76  	protocols := "https,http"
    77  	if options.UseHTTPS {
    78  		protocols = "https"
    79  	}
    80  
    81  	permissions := options.QueueSASPermissions.buildString()
    82  	stringToSign, err := queueSASStringToSign(q.qsc.client.apiVersion, canonicalizedResource, signedStart, signedExpiry, options.IP, permissions, protocols, options.Identifier)
    83  	if err != nil {
    84  		return "", err
    85  	}
    86  
    87  	sig := q.qsc.client.computeHmac256(stringToSign)
    88  	sasParams := url.Values{
    89  		"sv":  {q.qsc.client.apiVersion},
    90  		"se":  {signedExpiry},
    91  		"sp":  {permissions},
    92  		"sig": {sig},
    93  	}
    94  
    95  	if q.qsc.client.apiVersion >= "2015-04-05" {
    96  		sasParams.Add("spr", protocols)
    97  		addQueryParameter(sasParams, "sip", options.IP)
    98  	}
    99  
   100  	uri := q.qsc.client.getEndpoint(queueServiceName, q.buildPath(), nil)
   101  	sasURL, err := url.Parse(uri)
   102  	if err != nil {
   103  		return "", err
   104  	}
   105  	sasURL.RawQuery = sasParams.Encode()
   106  	return sasURL.String(), nil
   107  }
   108  
   109  func queueSASStringToSign(signedVersion, canonicalizedResource, signedStart, signedExpiry, signedIP, signedPermissions, protocols, signedIdentifier string) (string, error) {
   110  
   111  	if signedVersion >= "2015-02-21" {
   112  		canonicalizedResource = "/queue" + canonicalizedResource
   113  	}
   114  
   115  	// https://msdn.microsoft.com/en-us/library/azure/dn140255.aspx#Anchor_12
   116  	if signedVersion >= "2015-04-05" {
   117  		return fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s",
   118  			signedPermissions,
   119  			signedStart,
   120  			signedExpiry,
   121  			canonicalizedResource,
   122  			signedIdentifier,
   123  			signedIP,
   124  			protocols,
   125  			signedVersion), nil
   126  
   127  	}
   128  
   129  	// reference: http://msdn.microsoft.com/en-us/library/azure/dn140255.aspx
   130  	if signedVersion >= "2013-08-15" {
   131  		return fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s", signedPermissions, signedStart, signedExpiry, canonicalizedResource, signedIdentifier, signedVersion), nil
   132  	}
   133  
   134  	return "", errors.New("storage: not implemented SAS for versions earlier than 2013-08-15")
   135  }
   136  

View as plain text