1 |
|
2 |
|
3 | import { Constants, CosmosKeyType, SasTokenPermissionKind } from "../common";
|
4 | import { encodeUTF8 } from "./encode";
|
5 | import { hmac } from "./hmac";
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | export async function createAuthorizationSasToken(masterKey, sasTokenProperties) {
|
11 | let resourcePrefixPath = "";
|
12 | if (typeof sasTokenProperties.databaseName === "string" &&
|
13 | sasTokenProperties.databaseName !== "") {
|
14 | resourcePrefixPath += `/${Constants.Path.DatabasesPathSegment}/${sasTokenProperties.databaseName}`;
|
15 | }
|
16 | if (typeof sasTokenProperties.containerName === "string" &&
|
17 | sasTokenProperties.containerName !== "") {
|
18 | if (sasTokenProperties.databaseName === "") {
|
19 | throw new Error(`illegalArgumentException : ${sasTokenProperties.databaseName} \
|
20 | is an invalid database name`);
|
21 | }
|
22 | resourcePrefixPath += `/${Constants.Path.CollectionsPathSegment}/${sasTokenProperties.containerName}`;
|
23 | }
|
24 | if (typeof sasTokenProperties.resourceName === "string" &&
|
25 | sasTokenProperties.resourceName !== "") {
|
26 | if (sasTokenProperties.containerName === "") {
|
27 | throw new Error(`illegalArgumentException : ${sasTokenProperties.containerName} \
|
28 | is an invalid container name`);
|
29 | }
|
30 | switch (sasTokenProperties.resourceKind) {
|
31 | case "ITEM":
|
32 | resourcePrefixPath += `${Constants.Path.Root}${Constants.Path.DocumentsPathSegment}`;
|
33 | break;
|
34 | case "STORED_PROCEDURE":
|
35 | resourcePrefixPath += `${Constants.Path.Root}${Constants.Path.StoredProceduresPathSegment}`;
|
36 | break;
|
37 | case "USER_DEFINED_FUNCTION":
|
38 | resourcePrefixPath += `${Constants.Path.Root}${Constants.Path.UserDefinedFunctionsPathSegment}`;
|
39 | break;
|
40 | case "TRIGGER":
|
41 | resourcePrefixPath += `${Constants.Path.Root}${Constants.Path.TriggersPathSegment}`;
|
42 | break;
|
43 | default:
|
44 | throw new Error(`illegalArgumentException : ${sasTokenProperties.resourceKind} \
|
45 | is an invalid resource kind`);
|
46 | break;
|
47 | }
|
48 | resourcePrefixPath += `${Constants.Path.Root}${sasTokenProperties.resourceName}${Constants.Path.Root}`;
|
49 | }
|
50 | sasTokenProperties.resourcePath = resourcePrefixPath.toString();
|
51 | let partitionRanges = "";
|
52 | if (sasTokenProperties.partitionKeyValueRanges !== undefined &&
|
53 | sasTokenProperties.partitionKeyValueRanges.length > 0) {
|
54 | if (typeof sasTokenProperties.resourceKind !== "string" &&
|
55 | sasTokenProperties.resourceKind !== "ITEM") {
|
56 | throw new Error(`illegalArgumentException : ${sasTokenProperties.resourceKind} \
|
57 | is an invalid partition key value range`);
|
58 | }
|
59 | sasTokenProperties.partitionKeyValueRanges.forEach((range) => {
|
60 | partitionRanges += `${encodeUTF8(range)},`;
|
61 | });
|
62 | }
|
63 | if (sasTokenProperties.controlPlaneReaderScope === 0) {
|
64 | sasTokenProperties.controlPlaneReaderScope += SasTokenPermissionKind.ContainerReadAny;
|
65 | sasTokenProperties.controlPlaneWriterScope += SasTokenPermissionKind.ContainerReadAny;
|
66 | }
|
67 | if (sasTokenProperties.dataPlaneReaderScope === 0 &&
|
68 | sasTokenProperties.dataPlaneWriterScope === 0) {
|
69 | sasTokenProperties.dataPlaneReaderScope = SasTokenPermissionKind.ContainerFullAccess;
|
70 | sasTokenProperties.dataPlaneWriterScope = SasTokenPermissionKind.ContainerFullAccess;
|
71 | }
|
72 | if (typeof sasTokenProperties.keyType !== "number" ||
|
73 | typeof sasTokenProperties.keyType === undefined) {
|
74 | switch (sasTokenProperties.keyType) {
|
75 | case CosmosKeyType.PrimaryMaster:
|
76 | sasTokenProperties.keyType = 1;
|
77 | break;
|
78 | case CosmosKeyType.SecondaryMaster:
|
79 | sasTokenProperties.keyType = 2;
|
80 | break;
|
81 | case CosmosKeyType.PrimaryReadOnly:
|
82 | sasTokenProperties.keyType = 3;
|
83 | break;
|
84 | case CosmosKeyType.SecondaryReadOnly:
|
85 | sasTokenProperties.keyType = 4;
|
86 | break;
|
87 | default:
|
88 | throw new Error(`illegalArgumentException : ${sasTokenProperties.keyType} \
|
89 | is an invalid key type`);
|
90 | break;
|
91 | }
|
92 | }
|
93 | const payload = sasTokenProperties.user +
|
94 | "\n" +
|
95 | sasTokenProperties.userTag +
|
96 | "\n" +
|
97 | sasTokenProperties.resourcePath +
|
98 | "\n" +
|
99 | partitionRanges +
|
100 | "\n" +
|
101 | utcsecondsSinceEpoch(sasTokenProperties.startTime).toString(16) +
|
102 | "\n" +
|
103 | utcsecondsSinceEpoch(sasTokenProperties.expiryTime).toString(16) +
|
104 | "\n" +
|
105 | sasTokenProperties.keyType +
|
106 | "\n" +
|
107 | sasTokenProperties.controlPlaneReaderScope.toString(16) +
|
108 | "\n" +
|
109 | sasTokenProperties.controlPlaneWriterScope.toString(16) +
|
110 | "\n" +
|
111 | sasTokenProperties.dataPlaneReaderScope.toString(16) +
|
112 | "\n" +
|
113 | sasTokenProperties.dataPlaneWriterScope.toString(16) +
|
114 | "\n";
|
115 | const signedPayload = await hmac(masterKey, Buffer.from(payload).toString("base64"));
|
116 | return "type=sas&ver=1.0&sig=" + signedPayload + ";" + Buffer.from(payload).toString("base64");
|
117 | }
|
118 |
|
119 |
|
120 |
|
121 |
|
122 | export function utcsecondsSinceEpoch(date) {
|
123 | return Math.round(date.getTime() / 1000);
|
124 | }
|
125 |
|
\ | No newline at end of file |