1 package storage
2
3
4
5
6 import (
7 "errors"
8 "fmt"
9 "net/url"
10 "strings"
11 "time"
12 )
13
14
15
16
17 type QueueSASOptions struct {
18 QueueSASPermissions
19 SASOptions
20 }
21
22
23
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
50
51
52
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
60
61
62
63
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
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
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