From 439feaff4fd0699d7bb5e8f67eec0dd6f0769cc4 Mon Sep 17 00:00:00 2001 From: GZ Date: Tue, 30 Jul 2024 16:45:18 -0700 Subject: [PATCH] chore(apigateway): enhance code arounds method authorizers (#30978) ### Issue # (if applicable) ### Reason for this change Add comments and enhance the code around method authorizers. ### Description of changes No behavioural change, should only include comments, variables name update and re-ordering. ### Description of how you validated changes All existing tests pass. ### Checklist - [ ] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-cdk-lib/aws-apigateway/lib/method.ts | 52 +++++++++++++++---- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/packages/aws-cdk-lib/aws-apigateway/lib/method.ts b/packages/aws-cdk-lib/aws-apigateway/lib/method.ts index b488def778e38..8f282d253dbcc 100644 --- a/packages/aws-cdk-lib/aws-apigateway/lib/method.ts +++ b/packages/aws-cdk-lib/aws-apigateway/lib/method.ts @@ -185,22 +185,35 @@ export class Method extends Resource { validateHttpMethod(this.httpMethod); const options = props.options || {}; - const defaultMethodOptions = props.resource.defaultMethodOptions || {}; + // do not use the default authorizer config in case if the provided authorizer type is None const authorizer = options.authorizationType === AuthorizationType.NONE && options.authorizer == undefined ? undefined : options.authorizer || defaultMethodOptions.authorizer; const authorizerId = authorizer?.authorizerId ? authorizer.authorizerId : undefined; - const authorizationTypeOption = options.authorizationType || defaultMethodOptions.authorizationType; - const authorizationType = authorizer?.authorizationType || authorizationTypeOption || AuthorizationType.NONE; - - // if the authorizer defines an authorization type and we also have an explicit option set, check that they are the same - if (authorizer?.authorizationType && authorizationTypeOption && authorizer?.authorizationType !== authorizationTypeOption) { - throw new Error(`${this.resource}/${this.httpMethod} - Authorization type is set to ${authorizationTypeOption} ` + - `which is different from what is required by the authorizer [${authorizer.authorizationType}]`); - } + /** + * Get and validate authorization type from the values set by API resource and method. + * + * REST API Resource + * └── defaultMethodOptions: Method options to use as a default for all methods created within this API unless custom options are specified. + * ├── authorizationType: Specifies the default authorization type unless custom options are specified, recommended to not be specified. + * └── authorizer: Specifies the default authorizer for all methods created within this API unless custom options are specified. + * └── authorizerType: The default authorization type of this authorizer. + * + * REST API Method + * └── options: Method options. + * ├── authorizationType: Specifies the authorization type, recommended to not be specified. + * └── authorizer: Specifies an authorizer to use for this method. + * └── authorizerType: The authorization type of this authorizer. + * + * Authorization type is first set to "authorizer.authorizerType", falling back to method's "authorizationType", + * falling back to API resource's default "authorizationType", and lastly "Authorizer.NONE". + * + * Note that "authorizer.authorizerType" should match method or resource's "authorizationType" if exists. + */ + const authorizationType = this.getMethodAuthorizationType(options, defaultMethodOptions, authorizer); // AuthorizationScope should only be applied to COGNITO_USER_POOLS AuthorizationType. const defaultScopes = options.authorizationScopes ?? defaultMethodOptions.authorizationScopes; @@ -303,6 +316,27 @@ export class Method extends Resource { this.methodResponses.push(methodResponse); } + /** + * Get API Gateway Method's authorization type + * @param options API Gateway Method's options to use + * @param defaultMethodOptions API Gateway resource's default Method's options to use + * @param authorizer Authorizer used for API Gateway Method + * @returns API Gateway Method's authorizer type + */ + private getMethodAuthorizationType(options: MethodOptions, defaultMethodOptions: MethodOptions, authorizer?: IAuthorizer): string { + const authorizerAuthType = authorizer?.authorizationType; + const optionsAuthType = options.authorizationType || defaultMethodOptions.authorizationType; + const finalAuthType = authorizerAuthType || optionsAuthType || AuthorizationType.NONE; + + // if the authorizer defines an authorization type and we also have an explicit option set, check that they are the same + if (authorizerAuthType && optionsAuthType && authorizerAuthType !== optionsAuthType) { + throw new Error(`${this.resource}/${this.httpMethod} - Authorization type is set to ${optionsAuthType} ` + + `which is different from what is required by the authorizer [${authorizerAuthType}]`); + } + + return finalAuthType; + } + private renderIntegration(bindResult: IntegrationConfig): CfnMethod.IntegrationProperty { const options = bindResult.options ?? {}; let credentials;