diff --git a/aws/components/userpool/setup.ftl b/aws/components/userpool/setup.ftl index f1cf2818..0e5b0bbc 100644 --- a/aws/components/userpool/setup.ftl +++ b/aws/components/userpool/setup.ftl @@ -11,7 +11,7 @@ [#local resources = occurrence.State.Resources] [#-- Baseline component lookup --] - [#local baselineLinks = getBaselineLinks(occurrence, [ "Encryption" ] )] + [#local baselineLinks = getBaselineLinks(occurrence, [ "Encryption", "OpsData" ] )] [#local baselineComponentIds = getBaselineComponentIds(baselineLinks)] [#local cmkKeyId = baselineComponentIds["Encryption"]!"" ] [#local cmkKeyArn = getReference(cmkKeyId, ARN_ATTRIBUTE_TYPE)] @@ -39,11 +39,18 @@ [/#if] [/#if] + [#local wafAclResources = resources["wafacl"]!{} ] + [#local wafSolution = solution.WAF] + [#local wafLogStreamingResources = resources["wafLogStreaming"]!{} ] + [#local smsVerification = false] [#local userPoolTriggerConfig = {}] [#local smsConfig = {}] [#local authProviders = []] + [#local loggingProfile = getLoggingProfile(occurrence)] + [#local securityProfile = getSecurityProfile(occurrence, core.Type)] + [#local defaultUserPoolClientRequired = false ] [#local defaultUserPoolClientConfigured = false ] @@ -799,6 +806,49 @@ [/#if] [#if deploymentSubsetRequired(USERPOOL_COMPONENT_TYPE, true) ] + + [#if wafLogStreamingResources?has_content ] + + [@setupLoggingFirehoseStream + occurrence=occurrence + componentSubset=LB_COMPONENT_TYPE + resourceDetails=wafLogStreamingResources + destinationLink=baselineLinks["OpsData"] + bucketPrefix="WAF" + cloudwatchEnabled=true + cmkKeyId=kmsKeyId + loggingProfile=loggingProfile + /] + + [@enableWAFLogging + wafaclId=wafAclResources.acl.Id + wafaclArn=getArn(wafAclResources.acl.Id) + componentSubset=LB_COMPONENT_TYPE + deliveryStreamId=wafLogStreamingResources["stream"].Id + deliveryStreamArns=[ wafLogStreamingResources["stream"].Arn ] + regional=true + /] + [/#if] + [#if wafAclResources?has_content ] + [#if deploymentSubsetRequired(LB_COMPONENT_TYPE, true) ] + [#-- Create a WAF ACL if required --] + [@createWAFAclFromSecurityProfile + id=wafAclResources.acl.Id + name=wafAclResources.acl.Name + metric=wafAclResources.acl.Name + wafSolution=wafSolution + securityProfile=securityProfile + occurrence=occurrence + regional=true + /] + [@createWAFAclAssociation + id=wafAclResources.association.Id + wafaclId=getArn(wafAclResources.acl.Id) + endpointId=getArn(userPoolId) + /] + [/#if] + [/#if] + [@createUserPool id=userPoolId name=userPoolName diff --git a/aws/components/userpool/state.ftl b/aws/components/userpool/state.ftl index 38efd6b9..e183ab48 100644 --- a/aws/components/userpool/state.ftl +++ b/aws/components/userpool/state.ftl @@ -80,6 +80,36 @@ [#local attrLbAuthHeader = occurrence.Configuration.Solution.AuthorizationHeader ] + [#local wafResources = {} ] + [#if solution.WAF.Enabled] + [#local wafResources = + { + "acl" : { + "Id" : formatResourceId(AWS_WAFV2_ACL_RESOURCE_TYPE, occurrence.Core.Id), + "Name" : occurrence.Core.FullName, + "Type" : AWS_WAFV2_ACL_RESOURCE_TYPE + }, + "association" : { + "Id" : formatResourceId(AWS_WAFV2_ACL_ASSOCIATION_RESOURCE_TYPE, occurrence.Core.Id), + "Type" : AWS_WAFV2_ACL_ASSOCIATION_RESOURCE_TYPE + } + } ] + [/#if] + + [#local wafLoggingEnabled = solution.WAF.Enabled && solution.WAF.Logging.Enabled ] + + [#local wafLogStreamResources = {}] + [#if wafLoggingEnabled ] + [#local wafLogStreamResources = + getLoggingFirehoseStreamResources( + core.Id, + core.FullName, + core.FullAbsolutePath, + "waflog", + "aws-waf-logs-" + )] + [/#if] + [#assign componentState = { "Resources" : { @@ -119,7 +149,9 @@ } }, {} - ), + ) + + attributeIfContent("wafacl", wafResources) + + attributeIfContent("wafLogStreaming", wafLogStreamResources), "Roles" : { "Inbound" : { "invoke" : { diff --git a/aws/services/waf/id.ftl b/aws/services/waf/id.ftl index b5b6634f..c93119ce 100644 --- a/aws/services/waf/id.ftl +++ b/aws/services/waf/id.ftl @@ -99,6 +99,19 @@ /] [/#list] +[@addOutputMapping + provider=AWS_PROVIDER + resourceType=AWS_WAFV2_ACL_RESOURCE_TYPE + mappings={ + REFERENCE_ATTRIBUTE_TYPE : { + "Attribute" : "Id" + }, + ARN_ATTRIBUTE_TYPE : { + "Attribute" : "Arn" + } + } +/] + [#function formatDependentWAFConditionId type resourceId extensions...] [#local matchSetResourceType = (getWAFConditionSetMappings(type)["ResourceType"]["hamlet"])!"" ] [#return diff --git a/aws/services/waf/resource.ftl b/aws/services/waf/resource.ftl index 1cee31f1..5d30bd21 100644 --- a/aws/services/waf/resource.ftl +++ b/aws/services/waf/resource.ftl @@ -424,6 +424,17 @@ )] [/#if] + [#if action == "Challenge" ] + [#switch rule["Action:CHALLENGE"].Engine] + [#case "CAPTCHA"] + [#local action = "CAPTCHA" ] + [#break] + [#case "Transparent"] + [#local action = "CHALLENGE"] + [#break] + [/#switch] + [/#if] + [#local statement = formatV2Conditions(rule.Conditions, valueSet, ruleId) ] [#local rateLimitRule = {}]