def test_auth_supplied_via_definition_body_uri(self): self.template_dict["Resources"]["HelloWorldApi"] = OrderedDict( [ ("Type", "AWS::Serverless::Api"), ( "Properties", OrderedDict( [ ("StageName", "Prod"), ( "DefinitionBody", { "swagger": "2.0", "info": {"version": "1.0", "title": "local"}, "paths": {"/hello": {"get": {"security": ["OAuth2"]}}}, }, ), ] ), ), ] ) # setup the lambda function with a restapiId which has definitionBody defined with auth on the route. self.template_dict["Resources"]["HelloWorldFunction"]["Properties"]["Events"]["HelloWorld"]["Properties"][ "RestApiId" ] = {"Ref": "HelloWorldApi"} _auth_per_resource = auth_per_resource({}, self.template_dict) self.assertEqual(_auth_per_resource, [("HelloWorldFunction", True)])
def deploy( self, stack_name, template_str, parameters, capabilities, no_execute_changeset, role_arn, notification_arns, s3_uploader, tags, region, fail_on_empty_changeset=True, confirm_changeset=False, ): auth_required_per_resource = auth_per_resource( sanitize_parameter_overrides(self.parameter_overrides), get_template_data(self.template_file)) for resource, authorization_required in auth_required_per_resource: if not authorization_required: click.secho(f"{resource} may not have authorization defined.", fg="yellow") try: result, changeset_type = self.deployer.create_and_wait_for_changeset( stack_name=stack_name, cfn_template=template_str, parameter_values=parameters, capabilities=capabilities, role_arn=role_arn, notification_arns=notification_arns, s3_uploader=s3_uploader, tags=tags, ) click.echo( self.MSG_SHOWCASE_CHANGESET.format(changeset_id=result["Id"])) if no_execute_changeset: return if confirm_changeset: click.secho(self.MSG_CONFIRM_CHANGESET_HEADER, fg="yellow") click.secho("=" * len(self.MSG_CONFIRM_CHANGESET_HEADER), fg="yellow") if not click.confirm(f"{self.MSG_CONFIRM_CHANGESET}", default=False): return self.deployer.execute_changeset(result["Id"], stack_name) self.deployer.wait_for_execute(stack_name, changeset_type) click.echo( self.MSG_EXECUTE_SUCCESS.format(stack_name=stack_name, region=region)) except deploy_exceptions.ChangeEmptyError as ex: if fail_on_empty_changeset: raise click.echo(str(ex))
def test_auth_per_resource_auth_on_event_properties(self): event_properties = self.template_dict["Resources"][ "HelloWorldFunction"]["Properties"]["Events"]["HelloWorld"][ "Properties"] # setup authorizer and auth explicitly on the event properties. event_properties["Auth"] = {"ApiKeyRequired": True, "Authorizer": None} self.template_dict["Resources"]["HelloWorldFunction"]["Properties"][ "Events"]["HelloWorld"]["Properties"] = event_properties _auth_per_resource = auth_per_resource( [Stack("", "", "", {}, self.template_dict)]) self.assertEqual(_auth_per_resource, [("HelloWorldFunction", True)])
def prompt_authorization(self, stacks: List[Stack]): auth_required_per_resource = auth_per_resource(stacks) for resource, authorization_required in auth_required_per_resource: if not authorization_required: auth_confirm = confirm( f"\t{self.start_bold}{resource} may not have authorization defined, Is this okay?{self.end_bold}", default=False, ) if not auth_confirm: raise GuidedDeployFailedError( msg="Security Constraints Not Satisfied!")
def test_auth_per_resource_defined_on_api_resource(self): self.template_dict["Resources"]["HelloWorldApi"] = OrderedDict( [ ("Type", "AWS::Serverless::Api"), ("Properties", OrderedDict([("StageName", "Prod"), ("Auth", OrderedDict([("ApiKeyRequired", True)]))])), ] ) # setup the lambda function with a restapiId which has Auth defined. self.template_dict["Resources"]["HelloWorldFunction"]["Properties"]["Events"]["HelloWorld"]["Properties"][ "RestApiId" ] = {"Ref": "HelloWorldApi"} _auth_per_resource = auth_per_resource({}, self.template_dict) self.assertEqual(_auth_per_resource, [("HelloWorldFunction", True)])
def prompt_authorization(self, parameter_overrides): auth_required_per_resource = auth_per_resource( parameter_overrides, get_template_data(self.template_file)) for resource, authorization_required in auth_required_per_resource: if not authorization_required: auth_confirm = confirm( f"\t{self.start_bold}{resource} may not have authorization defined, Is this okay?{self.end_bold}", default=False, ) if not auth_confirm: raise GuidedDeployFailedError( msg="Security Constraints Not Satisfied!")
def test_auth_supplied_via_definition_body_uri_instrinsics_involved_unable_to_determine( self): self.template_dict["Resources"]["HelloWorldApi"] = OrderedDict([ ("Type", "AWS::Serverless::Api"), ( "Properties", OrderedDict([ ("StageName", "Prod"), ( "DefinitionBody", { "swagger": "2.0", "info": { "version": "1.0", "title": "local" }, "paths": { "/hello": { "Fn::If": [ "Condition", { "get": {} }, { "Ref": "AWS::NoValue" } ] } }, }, ), ]), ), ]) # setup the lambda function with a restapiId which has definitionBody defined with auth on the route. self.template_dict["Resources"]["HelloWorldFunction"]["Properties"][ "Events"]["HelloWorld"]["Properties"]["RestApiId"] = { "Ref": "HelloWorldApi" } _auth_per_resource = auth_per_resource( [Stack("", "", "", {}, self.template_dict)]) self.assertEqual(_auth_per_resource, [("HelloWorldFunction", False)])
def test_auth_per_resource_no_auth(self): _auth_per_resource = auth_per_resource( [Stack("", "", "", {}, self.template_dict)]) self.assertEqual(_auth_per_resource, [("HelloWorldFunction", False)])
def deploy( self, stack_name, template_str, parameters, capabilities, no_execute_changeset, role_arn, notification_arns, s3_uploader, tags, region, fail_on_empty_changeset=True, confirm_changeset=False, ): """ Deploy the stack to cloudformation. - if changeset needs confirmation, it will prompt for customers to confirm. - if no_execute_changeset is True, the changeset won't be executed. Parameters ---------- stack_name : str name of the stack template_str : str the string content of the template parameters : List[Dict] List of parameters capabilities : List[str] List of capabilities no_execute_changeset : bool A bool indicating whether to execute changeset role_arn : str the Arn of the role to create changeset notification_arns : List[str] Arns for sending notifications s3_uploader : S3Uploader S3Uploader object to upload files to S3 buckets tags : List[str] List of tags passed to CloudFormation region : str AWS region to deploy the stack to fail_on_empty_changeset : bool Should fail when changeset is empty confirm_changeset : bool Should wait for customer's confirm before executing the changeset """ stacks, _ = SamLocalStackProvider.get_stacks( self.template_file, parameter_overrides=sanitize_parameter_overrides( self.parameter_overrides)) auth_required_per_resource = auth_per_resource(stacks) for resource, authorization_required in auth_required_per_resource: if not authorization_required: click.secho(f"{resource} may not have authorization defined.", fg="yellow") try: result, changeset_type = self.deployer.create_and_wait_for_changeset( stack_name=stack_name, cfn_template=template_str, parameter_values=parameters, capabilities=capabilities, role_arn=role_arn, notification_arns=notification_arns, s3_uploader=s3_uploader, tags=tags, ) click.echo( self.MSG_SHOWCASE_CHANGESET.format(changeset_id=result["Id"])) if no_execute_changeset: return if confirm_changeset: click.secho(self.MSG_CONFIRM_CHANGESET_HEADER, fg="yellow") click.secho("=" * len(self.MSG_CONFIRM_CHANGESET_HEADER), fg="yellow") if not click.confirm(f"{self.MSG_CONFIRM_CHANGESET}", default=False): return self.deployer.execute_changeset(result["Id"], stack_name) self.deployer.wait_for_execute(stack_name, changeset_type) click.echo( self.MSG_EXECUTE_SUCCESS.format(stack_name=stack_name, region=region)) except deploy_exceptions.ChangeEmptyError as ex: if fail_on_empty_changeset: raise click.echo(str(ex))