1
1
import { createSign } from "crypto" ;
2
2
3
- /** Input type to getSignedUrl and getSignedCookies. */
3
+ /**
4
+ * Input type to getSignedUrl and getSignedCookies.
5
+ * @public
6
+ */
4
7
export type CloudfrontSignInput = CloudfrontSignInputWithParameters | CloudfrontSignInputWithPolicy ;
5
8
6
- export interface CloudfrontSignInputBase {
7
- /** The URL string to sign. */
8
- url : string ;
9
+ /**
10
+ * @public
11
+ */
12
+ export type CloudfrontSignerCredentials = {
9
13
/** The ID of the Cloudfront key pair. */
10
14
keyPairId : string ;
11
15
/** The content of the Cloudfront private key. */
12
16
privateKey : string | Buffer ;
13
17
/** The passphrase of RSA-SHA1 key*/
14
18
passphrase ?: string ;
15
- /** The date string for when the signed URL or cookie can no longer be accessed. */
16
- dateLessThan ?: string ;
17
- /** The IP address string to restrict signed URL access to. */
18
- ipAddress ?: string ;
19
- /** The date string for when the signed URL or cookie can start to be accessed. */
20
- dateGreaterThan ?: string ;
21
- }
19
+ } ;
22
20
23
- export type CloudfrontSignInputWithParameters = CloudfrontSignInputBase & {
21
+ /**
22
+ * @public
23
+ */
24
+ export type CloudfrontSignInputWithParameters = CloudfrontSignerCredentials & {
25
+ /** The URL string to sign. */
26
+ url : string ;
24
27
/** The date string for when the signed URL or cookie can no longer be accessed */
25
28
dateLessThan : string ;
26
- /** For this type policy should not be provided. */
29
+ /** The date string for when the signed URL or cookie can start to be accessed. */
30
+ dateGreaterThan ?: string ;
31
+ /** The IP address string to restrict signed URL access to. */
32
+ ipAddress ?: string ;
33
+ /**
34
+ * [policy] should not be provided when using separate
35
+ * dateLessThan, dateGreaterThan, or ipAddress inputs.
36
+ */
27
37
policy ?: never ;
28
38
} ;
29
39
30
- export type CloudfrontSignInputWithPolicy = CloudfrontSignInputBase & {
31
- /** The JSON-encoded policy string */
32
- policy : string ;
40
+ /**
41
+ * @public
42
+ */
43
+ export type CloudfrontSignInputWithPolicy = CloudfrontSignerCredentials & {
33
44
/**
34
- * For this type dateLessThan should not be provided.
45
+ * The URL string to sign. Optional when policy is provided.
46
+ *
47
+ * This will be used as the initial url if calling getSignedUrl
48
+ * with a policy.
49
+ *
50
+ * This will be ignored if calling getSignedCookies with a policy.
35
51
*/
52
+ url ?: string ;
53
+ /** The JSON-encoded policy string */
54
+ policy : string ;
55
+ /** When using a policy, a separate dateLessThan should not be provided. */
36
56
dateLessThan ?: never ;
37
- /**
38
- * For this type ipAddress should not be provided.
39
- */
40
- ipAddress ?: string ;
41
- /**
42
- * For this type dateGreaterThan should not be provided.
43
- */
57
+ /** When using a policy, a separate dateGreaterThan should not be provided. */
44
58
dateGreaterThan ?: never ;
59
+ /** When using a policy, a separate ipAddress should not be provided. */
60
+ ipAddress ?: never ;
45
61
} ;
46
62
63
+ /**
64
+ * @public
65
+ */
47
66
export interface CloudfrontSignedCookiesOutput {
48
67
/** ID of the Cloudfront key pair. */
49
68
"CloudFront-Key-Pair-Id" : string ;
@@ -57,6 +76,7 @@ export interface CloudfrontSignedCookiesOutput {
57
76
58
77
/**
59
78
* Creates a signed URL string using a canned or custom policy.
79
+ * @public
60
80
* @returns the input URL with signature attached as query parameters.
61
81
*/
62
82
export function getSignedUrl ( {
@@ -74,6 +94,11 @@ export function getSignedUrl({
74
94
privateKey,
75
95
passphrase,
76
96
} ) ;
97
+
98
+ if ( ! url && ! policy ) {
99
+ throw new Error ( "@aws-sdk/cloudfront-signer: Please provide 'url' or 'policy'." ) ;
100
+ }
101
+
77
102
if ( policy ) {
78
103
cloudfrontSignBuilder . setCustomPolicy ( policy ) ;
79
104
} else {
@@ -85,10 +110,23 @@ export function getSignedUrl({
85
110
} ) ;
86
111
}
87
112
88
- const newURL = new URL ( url ) ;
113
+ let baseUrl : string | undefined ;
114
+ if ( url ) {
115
+ baseUrl = url ;
116
+ } else if ( policy ) {
117
+ const resources = getPolicyResources ( policy ! ) ;
118
+ if ( ! resources [ 0 ] ) {
119
+ throw new Error (
120
+ "@aws-sdk/cloudfront-signer: No URL provided and unable to determine URL from first policy statement resource."
121
+ ) ;
122
+ }
123
+ baseUrl = resources [ 0 ] . replace ( "*://" , "https://" ) ;
124
+ }
125
+
126
+ const newURL = new URL ( baseUrl ! ) ;
89
127
newURL . search = Array . from ( newURL . searchParams . entries ( ) )
90
128
. concat ( Object . entries ( cloudfrontSignBuilder . createCloudfrontAttribute ( ) ) )
91
- . filter ( ( [ key , value ] ) => value !== undefined )
129
+ . filter ( ( [ , value ] ) => value !== undefined )
92
130
. map ( ( [ key , value ] ) => `${ encodeURIComponent ( key ) } =${ encodeURIComponent ( value ) } ` )
93
131
. join ( "&" ) ;
94
132
@@ -97,6 +135,7 @@ export function getSignedUrl({
97
135
98
136
/**
99
137
* Creates signed cookies using a canned or custom policy.
138
+ * @public
100
139
* @returns an object with keys/values that can be added to cookies.
101
140
*/
102
141
export function getSignedCookies ( {
@@ -138,6 +177,9 @@ export function getSignedCookies({
138
177
return cookies ;
139
178
}
140
179
180
+ /**
181
+ * @internal
182
+ */
141
183
interface Policy {
142
184
Statement : Array < {
143
185
Resource : string ;
@@ -155,22 +197,45 @@ interface Policy {
155
197
} > ;
156
198
}
157
199
200
+ /**
201
+ * @internal
202
+ */
158
203
interface PolicyDates {
159
204
dateLessThan : number ;
160
205
dateGreaterThan ?: number ;
161
206
}
162
207
208
+ /**
209
+ * @internal
210
+ */
163
211
interface BuildPolicyInput extends PolicyDates , Pick < CloudfrontSignInput , "ipAddress" > {
164
212
resource : string ;
165
213
}
166
214
215
+ /**
216
+ * @internal
217
+ */
167
218
interface CloudfrontAttributes {
168
219
Expires ?: number ;
169
220
Policy ?: string ;
170
221
"Key-Pair-Id" : string ;
171
222
Signature : string ;
172
223
}
173
224
225
+ /**
226
+ * Utility to get the allowed resources of a policy.
227
+ * @internal
228
+ *
229
+ * @param policy - The JSON/JSON-encoded policy
230
+ */
231
+ function getPolicyResources ( policy : string | Policy ) {
232
+ const parsedPolicy : Policy = typeof policy === "string" ? JSON . parse ( policy ) : policy ;
233
+ return ( parsedPolicy ?. Statement ?? [ ] ) . map ( ( s ) => s . Resource ) ;
234
+ }
235
+
236
+ /**
237
+ * @internal
238
+ */
174
239
function getResource ( url : URL ) : string {
175
240
switch ( url . protocol ) {
176
241
case "http:" :
@@ -183,22 +248,18 @@ function getResource(url: URL): string {
183
248
}
184
249
}
185
250
251
+ /**
252
+ * @internal
253
+ */
186
254
class CloudfrontSignBuilder {
187
255
private keyPairId : string ;
188
256
private privateKey : string | Buffer ;
189
257
private passphrase ?: string ;
190
258
private policy : string ;
191
259
private customPolicy = false ;
192
260
private dateLessThan ?: number | undefined ;
193
- constructor ( {
194
- privateKey,
195
- keyPairId,
196
- passphrase,
197
- } : {
198
- keyPairId : string ;
199
- privateKey : string | Buffer ;
200
- passphrase ?: string ;
201
- } ) {
261
+
262
+ constructor ( { privateKey, keyPairId, passphrase } : CloudfrontSignerCredentials ) {
202
263
this . keyPairId = keyPairId ;
203
264
this . privateKey = privateKey ;
204
265
this . policy = "" ;
@@ -371,3 +432,16 @@ class CloudfrontSignBuilder {
371
432
} ;
372
433
}
373
434
}
435
+
436
+ /**
437
+ * @deprecated use CloudfrontSignInput, CloudfrontSignInputWithParameters, or CloudfrontSignInputWithPolicy.
438
+ */
439
+ export type CloudfrontSignInputBase = {
440
+ url : string ;
441
+ keyPairId : string ;
442
+ privateKey : string | Buffer ;
443
+ passphrase ?: string ;
444
+ dateLessThan ?: string ;
445
+ ipAddress ?: string ;
446
+ dateGreaterThan ?: string ;
447
+ } ;
0 commit comments