Skip to content

Commit 7f8e3a5

Browse files
committed
Add the code and documentation
1 parent bfc9c90 commit 7f8e3a5

File tree

5 files changed

+117
-224
lines changed

5 files changed

+117
-224
lines changed

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
11
# Azure-SAS-token
22

3-
Generate SAS token on the edge with cloudflare workers and this library
3+
Generate Azure SAS tokens on the edge with cloudflare workers and this library.
4+
5+
Zero depdendencies.
6+
7+
8+
## How to use the library
9+
10+
```ts
11+
import createBlobSas from './index'
12+
13+
const expireInMin = 5
14+
15+
const { blobSasUrl } = await createBlobSas({
16+
accountKey: 'asd',
17+
accountName: '1132',
18+
blobName: '123.txt',
19+
permissions: 'rw',
20+
containerName: 'container',
21+
expiresOn: new Date(new Date().valueOf() + expireInMin * 60 * 1000)
22+
})
23+
```

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"devDependencies": {
1919
"@cloudflare/workers-types": "^2.0.0",
2020
"prettier": "^2.1.2",
21-
"ts-loader": "^8.0.4",
2221
"typescript": "^4.0.3"
2322
},
2423
"prettier": {

src/index.ts

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,95 @@
1-
console.log('hello world')
1+
2+
type SASinput = {
3+
accountKey: string
4+
accountName: string
5+
containerName: string
6+
blobName: string
7+
permissions: string
8+
expiresOn: Date
9+
startsOn?: Date
10+
identifier?: string
11+
ipRange?: string
12+
protocol?: string
13+
cacheControl?: string
14+
contentDisposition?: string
15+
contentEncoding?: string
16+
contentLanguage?: string
17+
contentType?: string
18+
}
19+
20+
const truncatedISO8061Date = (date: Date) => {
21+
const dateString = date.toISOString()
22+
23+
return dateString.substring(0, dateString.length - 5) + 'Z'
24+
}
25+
26+
const computeHMACSHA256 = async (stringToSign: string, accountKey: string) => {
27+
const enc = new TextEncoder()
28+
const signatureUTF8 = enc.encode(stringToSign)
29+
const key = await crypto.subtle.importKey(
30+
'raw',
31+
Buffer.from(accountKey, 'base64'),
32+
{
33+
name: 'HMAC',
34+
hash: {
35+
name: 'SHA-256',
36+
},
37+
},
38+
false,
39+
['sign']
40+
)
41+
42+
const digest = await crypto.subtle.sign('HMAC', key, signatureUTF8)
43+
44+
return Buffer.from(digest).toString('base64')
45+
}
46+
47+
const getCanonicalName = (accountName: string, containerName: string, blobName?: string) => {
48+
const elements: string[] = [`/blob/${accountName}/${containerName}`]
49+
if (blobName) {
50+
elements.push(`/${blobName}`)
51+
}
52+
return elements.join('')
53+
}
54+
55+
const getSASqueryParams = async (input: SASinput) => {
56+
const resource = 'b'
57+
const version = '2018-11-09'
58+
const signedSnapshotTime = undefined
59+
60+
const stringToSign = [
61+
input.permissions ? input.permissions : '',
62+
input.startsOn ? truncatedISO8061Date(input.startsOn) : '',
63+
truncatedISO8061Date(input.expiresOn),
64+
getCanonicalName(input.accountName, input.containerName, input.blobName),
65+
input.identifier ? input.identifier : '',
66+
input.ipRange ? input.ipRange : '',
67+
input.protocol ? input.protocol : '',
68+
version,
69+
resource,
70+
signedSnapshotTime,
71+
input.cacheControl ? input.cacheControl : '',
72+
input.contentDisposition ? input.contentDisposition : '',
73+
input.contentEncoding ? input.contentEncoding : '',
74+
input.contentLanguage ? input.contentLanguage : '',
75+
input.contentType ? input.contentType : '',
76+
].join('\n')
77+
78+
const signature = await computeHMACSHA256(stringToSign, input.accountKey)
79+
80+
return `sv=${version}&spr=https&se=${encodeURIComponent(
81+
truncatedISO8061Date(input.expiresOn)
82+
)}&sr=b&sp=rw&sig=${encodeURIComponent(signature)}`
83+
}
84+
85+
export default async (input: SASinput) => {
86+
const url = [input.containerName, input.blobName].filter(el => el).join('/')
87+
const storageUri = new URL(url, `https://${input.accountName}.blob.core.windows.net`)
88+
const queryParams = await getSASqueryParams(input)
89+
90+
storageUri.search = queryParams
91+
92+
return {
93+
blobSasUrl: url.toString(),
94+
}
95+
}

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
"moduleResolution": "node",
77
"esModuleInterop": true,
88
"strict": true,
9+
"sourceMap": true,
910
"noUnusedLocals": true,
1011
"noUnusedParameters": true,
1112
"noImplicitReturns": true,
1213
"noFallthroughCasesInSwitch": true,
1314
"forceConsistentCasingInFileNames": true,
1415
"removeComments": true,
15-
"types": [],
1616
"outDir": "./dist"
1717
}
1818
}

yarn.lock

Lines changed: 0 additions & 220 deletions
Original file line numberDiff line numberDiff line change
@@ -7,232 +7,12 @@
77
resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-2.0.0.tgz#c57162155bd83744a0fa83276ffec0ad430f14e4"
88
integrity sha512-SFUPQzR5aV2TBLP4Re+xNX5KfAGArcRGA44OLulBDnfblEf3J+6kFvdJAQwFhFpqru3wImwT1cX0wahk6EeWTw==
99

10-
ansi-styles@^3.2.1:
11-
version "3.2.1"
12-
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
13-
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
14-
dependencies:
15-
color-convert "^1.9.0"
16-
17-
big.js@^5.2.2:
18-
version "5.2.2"
19-
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
20-
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
21-
22-
braces@^3.0.1:
23-
version "3.0.2"
24-
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
25-
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
26-
dependencies:
27-
fill-range "^7.0.1"
28-
29-
chalk@^2.3.0:
30-
version "2.4.2"
31-
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
32-
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
33-
dependencies:
34-
ansi-styles "^3.2.1"
35-
escape-string-regexp "^1.0.5"
36-
supports-color "^5.3.0"
37-
38-
color-convert@^1.9.0:
39-
version "1.9.3"
40-
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
41-
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
42-
dependencies:
43-
color-name "1.1.3"
44-
45-
46-
version "1.1.3"
47-
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
48-
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
49-
50-
core-util-is@~1.0.0:
51-
version "1.0.2"
52-
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
53-
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
54-
55-
emojis-list@^3.0.0:
56-
version "3.0.0"
57-
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
58-
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
59-
60-
enhanced-resolve@^4.0.0:
61-
version "4.3.0"
62-
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126"
63-
integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==
64-
dependencies:
65-
graceful-fs "^4.1.2"
66-
memory-fs "^0.5.0"
67-
tapable "^1.0.0"
68-
69-
errno@^0.1.3:
70-
version "0.1.7"
71-
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
72-
integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==
73-
dependencies:
74-
prr "~1.0.1"
75-
76-
escape-string-regexp@^1.0.5:
77-
version "1.0.5"
78-
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
79-
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
80-
81-
fill-range@^7.0.1:
82-
version "7.0.1"
83-
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
84-
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
85-
dependencies:
86-
to-regex-range "^5.0.1"
87-
88-
graceful-fs@^4.1.2:
89-
version "4.2.4"
90-
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
91-
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
92-
93-
has-flag@^3.0.0:
94-
version "3.0.0"
95-
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
96-
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
97-
98-
inherits@~2.0.3:
99-
version "2.0.4"
100-
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
101-
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
102-
103-
is-number@^7.0.0:
104-
version "7.0.0"
105-
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
106-
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
107-
108-
isarray@~1.0.0:
109-
version "1.0.0"
110-
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
111-
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
112-
113-
json5@^1.0.1:
114-
version "1.0.1"
115-
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
116-
integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
117-
dependencies:
118-
minimist "^1.2.0"
119-
120-
loader-utils@^1.0.2:
121-
version "1.4.0"
122-
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
123-
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
124-
dependencies:
125-
big.js "^5.2.2"
126-
emojis-list "^3.0.0"
127-
json5 "^1.0.1"
128-
129-
memory-fs@^0.5.0:
130-
version "0.5.0"
131-
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c"
132-
integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==
133-
dependencies:
134-
errno "^0.1.3"
135-
readable-stream "^2.0.1"
136-
137-
micromatch@^4.0.0:
138-
version "4.0.2"
139-
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
140-
integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
141-
dependencies:
142-
braces "^3.0.1"
143-
picomatch "^2.0.5"
144-
145-
minimist@^1.2.0:
146-
version "1.2.5"
147-
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
148-
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
149-
150-
picomatch@^2.0.5:
151-
version "2.2.2"
152-
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
153-
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
154-
15510
prettier@^2.1.2:
15611
version "2.1.2"
15712
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5"
15813
integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==
15914

160-
process-nextick-args@~2.0.0:
161-
version "2.0.1"
162-
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
163-
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
164-
165-
prr@~1.0.1:
166-
version "1.0.1"
167-
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
168-
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
169-
170-
readable-stream@^2.0.1:
171-
version "2.3.7"
172-
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
173-
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
174-
dependencies:
175-
core-util-is "~1.0.0"
176-
inherits "~2.0.3"
177-
isarray "~1.0.0"
178-
process-nextick-args "~2.0.0"
179-
safe-buffer "~5.1.1"
180-
string_decoder "~1.1.1"
181-
util-deprecate "~1.0.1"
182-
183-
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
184-
version "5.1.2"
185-
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
186-
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
187-
188-
semver@^6.0.0:
189-
version "6.3.0"
190-
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
191-
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
192-
193-
string_decoder@~1.1.1:
194-
version "1.1.1"
195-
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
196-
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
197-
dependencies:
198-
safe-buffer "~5.1.0"
199-
200-
supports-color@^5.3.0:
201-
version "5.5.0"
202-
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
203-
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
204-
dependencies:
205-
has-flag "^3.0.0"
206-
207-
tapable@^1.0.0:
208-
version "1.1.3"
209-
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
210-
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
211-
212-
to-regex-range@^5.0.1:
213-
version "5.0.1"
214-
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
215-
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
216-
dependencies:
217-
is-number "^7.0.0"
218-
219-
ts-loader@^8.0.4:
220-
version "8.0.4"
221-
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.4.tgz#02b9c91fbcfdb3114d8b1e98a3829265270eee7a"
222-
integrity sha512-5u8KF1SW8eCUb/Ff7At81e3wznPmT/27fvaGRO9CziVy+6NlPVRvrzSox4OwU0/e6OflOUB32Err4VquysCSAQ==
223-
dependencies:
224-
chalk "^2.3.0"
225-
enhanced-resolve "^4.0.0"
226-
loader-utils "^1.0.2"
227-
micromatch "^4.0.0"
228-
semver "^6.0.0"
229-
23015
typescript@^4.0.3:
23116
version "4.0.3"
23217
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5"
23318
integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==
234-
235-
util-deprecate@~1.0.1:
236-
version "1.0.2"
237-
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
238-
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=

0 commit comments

Comments
 (0)