11import { createSign } from "crypto" ;
22
3- /** Input type to getSignedUrl and getSignedCookies. */
3+ /**
4+ * Input type to getSignedUrl and getSignedCookies.
5+ * @public
6+ */
47export type CloudfrontSignInput = CloudfrontSignInputWithParameters | CloudfrontSignInputWithPolicy ;
58
6- export interface CloudfrontSignInputBase {
7- /** The URL string to sign. */
8- url : string ;
9+ /**
10+ * @public
11+ */
12+ export type CloudfrontSignerCredentials = {
913 /** The ID of the Cloudfront key pair. */
1014 keyPairId : string ;
1115 /** The content of the Cloudfront private key. */
1216 privateKey : string | Buffer ;
1317 /** The passphrase of RSA-SHA1 key*/
1418 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+ } ;
2220
23- export type CloudfrontSignInputWithParameters = CloudfrontSignInputBase & {
21+ /**
22+ * @public
23+ */
24+ export type CloudfrontSignInputWithParameters = CloudfrontSignerCredentials & {
25+ /** The URL string to sign. */
26+ url : string ;
2427 /** The date string for when the signed URL or cookie can no longer be accessed */
2528 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+ */
2737 policy ?: never ;
2838} ;
2939
30- export type CloudfrontSignInputWithPolicy = CloudfrontSignInputBase & {
31- /** The JSON-encoded policy string */
32- policy : string ;
40+ /**
41+ * @public
42+ */
43+ export type CloudfrontSignInputWithPolicy = CloudfrontSignerCredentials & {
3344 /**
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.
3551 */
52+ url ?: string ;
53+ /** The JSON-encoded policy string */
54+ policy : string ;
55+ /** When using a policy, a separate dateLessThan should not be provided. */
3656 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. */
4458 dateGreaterThan ?: never ;
59+ /** When using a policy, a separate ipAddress should not be provided. */
60+ ipAddress ?: never ;
4561} ;
4662
63+ /**
64+ * @public
65+ */
4766export interface CloudfrontSignedCookiesOutput {
4867 /** ID of the Cloudfront key pair. */
4968 "CloudFront-Key-Pair-Id" : string ;
@@ -57,6 +76,7 @@ export interface CloudfrontSignedCookiesOutput {
5776
5877/**
5978 * Creates a signed URL string using a canned or custom policy.
79+ * @public
6080 * @returns the input URL with signature attached as query parameters.
6181 */
6282export function getSignedUrl ( {
@@ -74,6 +94,11 @@ export function getSignedUrl({
7494 privateKey,
7595 passphrase,
7696 } ) ;
97+
98+ if ( ! url && ! policy ) {
99+ throw new Error ( "@aws-sdk/cloudfront-signer: Please provide 'url' or 'policy'." ) ;
100+ }
101+
77102 if ( policy ) {
78103 cloudfrontSignBuilder . setCustomPolicy ( policy ) ;
79104 } else {
@@ -85,10 +110,23 @@ export function getSignedUrl({
85110 } ) ;
86111 }
87112
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 ! ) ;
89127 newURL . search = Array . from ( newURL . searchParams . entries ( ) )
90128 . concat ( Object . entries ( cloudfrontSignBuilder . createCloudfrontAttribute ( ) ) )
91- . filter ( ( [ key , value ] ) => value !== undefined )
129+ . filter ( ( [ , value ] ) => value !== undefined )
92130 . map ( ( [ key , value ] ) => `${ encodeURIComponent ( key ) } =${ encodeURIComponent ( value ) } ` )
93131 . join ( "&" ) ;
94132
@@ -97,6 +135,7 @@ export function getSignedUrl({
97135
98136/**
99137 * Creates signed cookies using a canned or custom policy.
138+ * @public
100139 * @returns an object with keys/values that can be added to cookies.
101140 */
102141export function getSignedCookies ( {
@@ -138,6 +177,9 @@ export function getSignedCookies({
138177 return cookies ;
139178}
140179
180+ /**
181+ * @internal
182+ */
141183interface Policy {
142184 Statement : Array < {
143185 Resource : string ;
@@ -155,22 +197,45 @@ interface Policy {
155197 } > ;
156198}
157199
200+ /**
201+ * @internal
202+ */
158203interface PolicyDates {
159204 dateLessThan : number ;
160205 dateGreaterThan ?: number ;
161206}
162207
208+ /**
209+ * @internal
210+ */
163211interface BuildPolicyInput extends PolicyDates , Pick < CloudfrontSignInput , "ipAddress" > {
164212 resource : string ;
165213}
166214
215+ /**
216+ * @internal
217+ */
167218interface CloudfrontAttributes {
168219 Expires ?: number ;
169220 Policy ?: string ;
170221 "Key-Pair-Id" : string ;
171222 Signature : string ;
172223}
173224
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+ */
174239function getResource ( url : URL ) : string {
175240 switch ( url . protocol ) {
176241 case "http:" :
@@ -183,22 +248,18 @@ function getResource(url: URL): string {
183248 }
184249}
185250
251+ /**
252+ * @internal
253+ */
186254class CloudfrontSignBuilder {
187255 private keyPairId : string ;
188256 private privateKey : string | Buffer ;
189257 private passphrase ?: string ;
190258 private policy : string ;
191259 private customPolicy = false ;
192260 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 ) {
202263 this . keyPairId = keyPairId ;
203264 this . privateKey = privateKey ;
204265 this . policy = "" ;
@@ -371,3 +432,16 @@ class CloudfrontSignBuilder {
371432 } ;
372433 }
373434}
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