cloudformation.yaml (818 lines of code) (raw):
AWSTemplateFormatVersion: 2010-09-09
Description: gateway
Parameters:
AMI:
Description: AMI to use in the autoscaling group
Type: String
App:
Description: Application name
Default: identity-gateway
Type: String
IdapiBaseUrl:
Description: The base url for idapi
Type: AWS::SSM::Parameter::Value<String>
SignInPageUrl:
Description: Sign in page URL used as a fallback if auth redirect retrieval fails.
Type: AWS::SSM::Parameter::Value<String>
OauthBaseUrl:
Description: The base url for social sign-in with google or apple
Type: AWS::SSM::Parameter::Value<String>
OktaOrgUrl:
Description: The org url for interacting with okta APIs
Type: AWS::SSM::Parameter::Value<String>
MembersDataApiUrl:
Description: The url for members-data-api
Type: AWS::SSM::Parameter::Value<String>
RedisHost:
Description: The Redis server URL, used for rate limiting.
Type: AWS::SSM::Parameter::Value<String>
CertificateArn:
Description: ARN of certificate for loadbalancer use.
Type: String
KeyName:
Description: The EC2 Key Pair to allow SSH access to the instances
Type: AWS::EC2::KeyPair::KeyName
AlarmEmailAddress:
Description: Email address to send CloudWatch alerts
Type: String
PrivateVpcSubnets:
Description: Private VPC Subnet for the EC2 instances.
Type: List<AWS::EC2::Subnet::Id>
PublicVpcSubnets:
Description: Public VPC Subnet for the ELB
Type: List<AWS::EC2::Subnet::Id>
Stack:
Description: tag
Default: identity
Type: String
Stage:
Description: Deployment environment
Default: CODE
Type: String
AllowedValues:
- CODE
- PROD
SsmManagedPolicyArn:
Description: The ARN for the ssm iam role
Type: String
VpcId:
Description: VPC id of VPC for this service to use
Type: String
KinesisStream:
Description: Kinesis Stream name for logging
Type: AWS::SSM::Parameter::Value<String>
Default: /account/services/logging.stream/name
LoadBalancerLogsS3Bucket:
Description: S3 Bucket to write ELB access logs to
Type: String
IdentityArtifactBucket:
Description: S3 Bucket to read identity artifacts from
Type: String
IdentityConfigBucket:
Description: S3 Bucket to read identity config from
Type: String
Mappings:
StageVariables:
CODE:
BaseUri: profile.code.dev-theguardian.com
DefaultReturnUri: https://m.code.dev-theguardian.com
MaxInstances: 2
MinInstances: 1
LatencyAlarmThreshold: 5
LatencyAlarmPeriod: 1200
PROD:
BaseUri: profile.theguardian.com
DefaultReturnUri: https://theguardian.com
MaxInstances: 12
MinInstances: 3
LatencyAlarmThreshold: 0.5
LatencyAlarmPeriod: 60
AlarmPriorities:
P1: 'CRITICAL Respond Immediately'
P2: 'URGENT 9-5'
P3: 'MODERATE'
Conditions:
IsProd: !Equals [!Ref Stage, PROD]
NotIsProd: !Not [!Equals [!Ref Stage, PROD]]
Resources:
AppRole:
Type: AWS::IAM::Role
Properties:
Path: '/'
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- !Ref SsmManagedPolicyArn
Policies:
- PolicyName: root
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: s3:GetObject
Resource:
- !Sub arn:aws:s3:::${IdentityArtifactBucket}/${Stage}/${App}/*
- Effect: Allow
Action: s3:GetObject
Resource:
- !Sub arn:aws:s3:::${IdentityConfigBucket}/${Stage}/${App}/*
- PolicyName: DevxLogs
PolicyDocument:
Statement:
- Effect: Allow
Action:
- ec2:DescribeTags
- ec2:DescribeInstances
Resource: '*'
- Effect: Allow
Action:
- kinesis:DescribeStream
- kinesis:PutRecord
- kinesis:PutRecords
Resource:
- !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${KinesisStream}
- PolicyName: GetParameters
PolicyDocument:
Statement:
- Effect: Allow
Action:
- ssm:GetParameter
Resource:
- !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${Stack}/${App}/${Stage}/*
- PolicyName: PushMetrics
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: cloudwatch:PutMetricData
Resource: '*'
- PolicyName: DescribeASG
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- autoscaling:DescribeAutoScalingGroups
- autoscaling:DescribeAutoScalingInstances
Resource: '*'
- PolicyName: SendEmailSES
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: ses:SendEmail
Resource: '*'
- PolicyName: SSMTunnel
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- ec2messages:AcknowledgeMessage
- ec2messages:DeleteMessage
- ec2messages:FailMessage
- ec2messages:GetEndpoint
- ec2messages:GetMessages
- ec2messages:SendReply
- ssm:UpdateInstanceInformation
- ssm:ListInstanceAssociations
- ssm:DescribeInstanceProperties
- ssm:DescribeDocumentParameters
- ssmmessages:CreateControlChannel
- ssmmessages:CreateDataChannel
- ssmmessages:OpenControlChannel
- ssmmessages:OpenDataChannel
Resource: '*'
GithubActionsSESSendEmailsRole:
Type: AWS::IAM::Role
Condition: NotIsProd
Properties:
RoleName: GithubActionsSESSendEmailsRole
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRoleWithWebIdentity
Principal:
Federated: !Sub arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com
Condition:
StringLike:
# All GitHub Actions running from the guardian/gateway repository.
token.actions.githubusercontent.com:sub: !Sub repo:guardian/gateway:*
Policies:
- PolicyName: SendEmailSES
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: ses:SendEmail
Resource: '*'
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
LaunchTemplate:
LaunchTemplateId: !Ref LaunchTemplate
Version: !GetAtt 'LaunchTemplate.LatestVersionNumber'
HealthCheckType: ELB
HealthCheckGracePeriod: 300
MinSize: !FindInMap [StageVariables, !Ref Stage, MinInstances]
MaxSize: !FindInMap [StageVariables, !Ref Stage, MaxInstances]
TargetGroupARNs:
- !Ref TargetGroup
VPCZoneIdentifier: !Ref PrivateVpcSubnets
Tags:
- Key: Name
Value: !Sub '${Stage}:${App}'
PropagateAtLaunch: 'true'
- Key: App
Value: !Ref App
PropagateAtLaunch: true
- Key: Stack
Value: !Ref Stack
PropagateAtLaunch: true
- Key: Stage
Value: !Ref Stage
PropagateAtLaunch: true
- Key: LogKinesisStreamName
Value: !Ref KinesisStream
PropagateAtLaunch: true
- Key: SystemdUnit
Value: identity-gateway.service
PropagateAtLaunch: true
LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: !Sub '${Stage}-${Stack}-${App}'
LaunchTemplateData:
ImageId: !Ref AMI
IamInstanceProfile:
Arn: !GetAtt 'InstanceProfile.Arn'
InstanceType: t4g.small
KeyName: !Ref KeyName
SecurityGroupIds:
- !Ref InstanceSecurityGroup
MetadataOptions:
HttpTokens: required
UserData:
Fn::Base64: !Sub
- |+
#!/bin/bash -ev
mkdir /etc/gu
# Get Riff Raff deployed artefact S3
aws s3 cp s3://${IdentityArtifactBucket}/${Stage}/${App}/${App}.zip /etc/gu
unzip -o /etc/gu/${App}.zip -d /etc/gu
# Get Rate Limiter configuration file
# Try multiple times to the config file. The s3 cp command can fail when called immediately on instance startup.
while true; do
if \
aws s3 cp s3://${IdentityConfigBucket}/${Stage}/${App}/.ratelimit.json /etc/gu/.ratelimit.json
then break
fi
sleep 1
done
# Setup user
groupadd identity-gateway
useradd -r -s /usr/bin/nologin -g identity-gateway identity-gateway
chown -R identity-gateway:identity-gateway /etc/gu
# Setup logs
touch /var/log/identity-gateway.log
chown identity-gateway:identity-gateway /var/log/identity-gateway.log
# Try multiple times to get parameter store values. The SSM command can fail when called immediately on instance startup.
while true; do
if \
IDAPI_CLIENT_ACCESS_TOKEN=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/idapi-client-access-token' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text") && \
APP_SECRET=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/appSecret' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text") && \
GOOGLE_RECAPTCHA_SITE_KEY=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/recaptcha-site-key' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text") && \
GOOGLE_RECAPTCHA_SECRET_KEY=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/recaptcha-secret-key' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text") && \
REDIS_PASSWORD=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/redis-password' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text") && \
ENCRYPTION_SECRET_KEY=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/encryption-secret-key' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text") && \
OKTA_API_TOKEN=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/okta-api-token' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text") && \
OKTA_CUSTOM_OAUTH_SERVER=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/oktaCustomOAuthServer' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text") && \
OKTA_CLIENT_ID=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/oktaClientId' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text") && \
OKTA_CLIENT_SECRET=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/oktaClientSecret' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text")
OKTA_IDP_APPLE=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/oktaIdpApple' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text")
OKTA_IDP_GOOGLE=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/oktaIdpGoogle' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text")
OKTA_GUARDIAN_USERS_ALL_GROUP_ID=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/oktaGuardianUsersAllGroupId' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text")
USER_BENEFITS_API_URL=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/user-benefits-api-url' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text")
DELETE_ACCOUNT_STEP_FUNCTION_URL=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/deleteAccountStepFunctionUrl' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text")
DELETE_ACCOUNT_STEP_FUNCTION_API_KEY=$(aws ssm get-parameter --name '/${Stack}/${App}/${Stage}/deleteAccountStepFunctionApiKey' --with-decryption --region eu-west-1 --query="Parameter.Value" --output="text")
then break
fi
sleep 1
done
# systemd setup
cat > /etc/systemd/system/identity-gateway.service <<EOL
[Service]
ExecStart=/bin/sh -ec '/usr/bin/node /etc/gu/server.js 2>&1'
Restart=always
StandardOutput=journal
StandardError=journal
SyslogIdentifier=identity-gateway
User=identity-gateway
Group=identity-gateway
Environment=NODE_ENV=production
Environment=PORT=9233
Environment=IDAPI_CLIENT_ACCESS_TOKEN=$IDAPI_CLIENT_ACCESS_TOKEN
Environment=IDAPI_BASE_URL=${IdapiBaseUrl}
Environment=SIGN_IN_PAGE_URL=${SignInPageUrl}
Environment=OAUTH_BASE_URL=${OauthBaseUrl}
Environment=BASE_URI=${BaseUri}
Environment=DEFAULT_RETURN_URI=${DefaultReturnUri}
Environment=STAGE=${Stage}
Environment=IS_HTTPS=true
Environment=APP_SECRET=$APP_SECRET
Environment=GOOGLE_RECAPTCHA_SITE_KEY=$GOOGLE_RECAPTCHA_SITE_KEY
Environment=GOOGLE_RECAPTCHA_SECRET_KEY=$GOOGLE_RECAPTCHA_SECRET_KEY
Environment=ENCRYPTION_SECRET_KEY=$ENCRYPTION_SECRET_KEY
Environment=OKTA_ORG_URL=${OktaOrgUrl}
Environment=OKTA_API_TOKEN=$OKTA_API_TOKEN
Environment=OKTA_CUSTOM_OAUTH_SERVER=$OKTA_CUSTOM_OAUTH_SERVER
Environment=OKTA_CLIENT_ID=$OKTA_CLIENT_ID
Environment=OKTA_CLIENT_SECRET=$OKTA_CLIENT_SECRET
Environment=OKTA_IDP_APPLE=$OKTA_IDP_APPLE
Environment=OKTA_IDP_GOOGLE=$OKTA_IDP_GOOGLE
Environment=OKTA_GUARDIAN_USERS_ALL_GROUP_ID=$OKTA_GUARDIAN_USERS_ALL_GROUP_ID
Environment=REDIS_PASSWORD=$REDIS_PASSWORD
Environment=REDIS_HOST=${RedisHost}
Environment=REDIS_SSL_ON=true
Environment=MEMBERS_DATA_API_URL=${MembersDataApiUrl}
Environment=USER_BENEFITS_API_URL=$USER_BENEFITS_API_URL
Environment=DELETE_ACCOUNT_STEP_FUNCTION_URL=$DELETE_ACCOUNT_STEP_FUNCTION_URL
Environment=DELETE_ACCOUNT_STEP_FUNCTION_API_KEY=$DELETE_ACCOUNT_STEP_FUNCTION_API_KEY
[Install]
WantedBy=multi-user.target
EOL
systemctl enable identity-gateway
systemctl start identity-gateway
- BaseUri: !FindInMap [StageVariables, !Ref Stage, BaseUri]
DefaultReturnUri:
!FindInMap [StageVariables, !Ref Stage, DefaultReturnUri]
InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: '/'
Roles:
- !Ref AppRole
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow SSH and HTTPS access
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 9233
ToPort: 9233
SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub '${Stack}-${App}-${Stage}'
Subnets: !Ref PublicVpcSubnets
SecurityGroups:
- !Ref LoadBalancerSecurityGroup
Tags:
- Key: App
Value: !Ref App
- Key: Stack
Value: !Ref Stack
- Key: Stage
Value: !Ref Stage
LoadBalancerAttributes:
- Key: access_logs.s3.enabled
Value: true
- Key: access_logs.s3.bucket
Value: !Ref 'LoadBalancerLogsS3Bucket'
- Key: access_logs.s3.prefix
Value: !Sub 'ELBLogs/${Stack}/${App}/${Stage}'
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
Certificates:
- CertificateArn: !Ref CertificateArn
DefaultActions:
- Type: forward
TargetGroupArn:
Ref: TargetGroup
LoadBalancerArn:
Ref: LoadBalancer
Port: 443
Protocol: HTTPS
SslPolicy: ELBSecurityPolicy-TLS-1-2-2017-01
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTPS traffic and egress to 9233
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 9233
ToPort: 9233
CidrIp: 0.0.0.0/0
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub ${Stage}-${Stack}-${App}
Port: 9233
Protocol: HTTP
VpcId:
Ref: VpcId
HealthCheckIntervalSeconds: 10
HealthCheckPath: /healthcheck
HealthCheckPort: 9233
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
UnhealthyThresholdCount: 2
Matcher:
HttpCode: 200
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: 45
DependsOn:
- LoadBalancer
TopicSendEmail:
Type: AWS::SNS::Topic
Condition: IsProd
Properties:
DisplayName: SendEmailToIdentityDev
Subscription:
- Endpoint: !Ref 'AlarmEmailAddress'
Protocol: email
HighLatencyScalingAlarm:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
AlarmName: !Sub
- '${Priority} - ${App}-${Stage} high load balancer latency scaling'
- Priority: !FindInMap [StageVariables, AlarmPriorities, P3]
AlarmDescription: !Sub
- 'Scale-Up if latency is greater than ${Threshold} seconds over last ${Period} seconds'
- Period: !FindInMap [StageVariables, !Ref 'Stage', LatencyAlarmPeriod]
Threshold:
!FindInMap [StageVariables, !Ref 'Stage', LatencyAlarmThreshold]
Namespace: AWS/ApplicationELB
MetricName: TargetResponseTime
Statistic: Average
ComparisonOperator: GreaterThanOrEqualToThreshold
Dimensions:
- Name: LoadBalancer
Value: !GetAtt 'LoadBalancer.LoadBalancerFullName'
Threshold:
!FindInMap [StageVariables, !Ref 'Stage', LatencyAlarmThreshold]
Period: !FindInMap [StageVariables, !Ref 'Stage', LatencyAlarmPeriod]
EvaluationPeriods: 1
AlarmActions:
- !Ref 'ScaleUpPolicy'
OKActions:
- !Ref 'ScaleDownPolicy'
ScaleUpPolicy:
Type: AWS::AutoScaling::ScalingPolicy
Properties:
AutoScalingGroupName: !Ref 'AutoScalingGroup'
AdjustmentType: ChangeInCapacity
ScalingAdjustment: 1
Cooldown: 300
ScaleDownPolicy:
Type: AWS::AutoScaling::ScalingPolicy
Properties:
AdjustmentType: ChangeInCapacity
AutoScalingGroupName: !Ref 'AutoScalingGroup'
Cooldown: 1800
ScalingAdjustment: -1
AlarmHighLatency:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
AlarmName: !Sub
- '${Priority} - ${App}-${Stage} high load balancer latency'
- Priority: !FindInMap [StageVariables, AlarmPriorities, P3]
AlarmDescription: !Sub
- 'Latency is greater than ${Threshold} seconds over ${Period} seconds for last 5 periods'
- Period: !FindInMap [StageVariables, !Ref 'Stage', LatencyAlarmPeriod]
Threshold:
!FindInMap [StageVariables, !Ref 'Stage', LatencyAlarmThreshold]
Namespace: AWS/ApplicationELB
MetricName: TargetResponseTime
Statistic: Average
ComparisonOperator: GreaterThanOrEqualToThreshold
Dimensions:
- Name: LoadBalancer
Value: !GetAtt 'LoadBalancer.LoadBalancerFullName'
Threshold:
!FindInMap [StageVariables, !Ref 'Stage', LatencyAlarmThreshold]
Period: !FindInMap [StageVariables, !Ref 'Stage', LatencyAlarmPeriod]
EvaluationPeriods: 5
AlarmActions:
- !Ref 'TopicSendEmail'
InsufficientDataActions:
- !Ref 'TopicSendEmail'
AlarmNoHealthyHosts:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
ActionsEnabled: 'true'
AlarmName: !Sub
- '${Priority} - ${App}-${Stage} insufficient healthy hosts'
- Priority: !FindInMap [StageVariables, AlarmPriorities, P3]
AlarmDescription: There are insufficient healthy hosts
ComparisonOperator: LessThanThreshold
EvaluationPeriods: 1
MetricName: HealthyHostCount
Namespace: AWS/ApplicationELB
Period: 60
Statistic: Average
Threshold: !FindInMap [StageVariables, !Ref 'Stage', MinInstances]
AlarmActions:
- !Ref 'TopicSendEmail'
InsufficientDataActions:
- !Ref 'TopicSendEmail'
OKActions:
- !Ref 'TopicSendEmail'
Dimensions:
- Name: LoadBalancer
Value: !GetAtt 'LoadBalancer.LoadBalancerFullName'
- Name: TargetGroup
Value: !GetAtt 'TargetGroup.TargetGroupFullName'
DependsOn:
- TargetGroup
- LoadBalancer
Alarm5XXSustained:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
ActionsEnabled: 'true'
AlarmName: !Sub
- '${Priority} - ${App}-${Stage} sustained 5xx errors'
- Priority: !FindInMap [StageVariables, AlarmPriorities, P2]
AlarmDescription: 'Sustained server errors detected'
AlarmActions:
- !Ref 'TopicSendEmail'
OKActions:
- !Ref 'TopicSendEmail'
InsufficientDataActions:
- !Ref 'TopicSendEmail'
ComparisonOperator: GreaterThanOrEqualToThreshold
Threshold: 15
EvaluationPeriods: 5
TreatMissingData: notBreaching
Metrics:
- Id: total5XXCount
Expression: backend5XXCount + elb5XXCount
Label: 'Count of Backend AND ELB 5XX'
- Id: backend5XXCount
MetricStat:
Metric:
Namespace: AWS/ApplicationELB
MetricName: HTTPCode_Target_5XX_Count
Dimensions:
- Name: LoadBalancer
Value: !GetAtt LoadBalancer.LoadBalancerFullName
- Name: TargetGroup
Value: !GetAtt TargetGroup.TargetGroupFullName
Period: 60
Stat: Sum
Unit: Count
ReturnData: false
- Id: elb5XXCount
MetricStat:
Metric:
Namespace: AWS/ApplicationELB
MetricName: HTTPCode_ELB_5XX_Count
Dimensions:
- Name: LoadBalancer
Value: !GetAtt LoadBalancer.LoadBalancerFullName
Period: 60
Stat: Sum
Unit: Count
ReturnData: false
SigninInactivityAlarm:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
AlarmName: !Sub
- '${Priority} - ${App} ${Stage} has had no new sign-ins in the last 20 minutes'
- Priority: !FindInMap [StageVariables, AlarmPriorities, P1]
AlarmDescription: No one has successfully signed ins in the last 20 minutes.
Metrics:
- Id: totalSignInCount
Expression: oktaSignInCount + oktaIdxSignInCount
Label: 'Total sign-ins in Okta'
- Id: oktaSignInCount
MetricStat:
Metric:
Namespace: Gateway
MetricName: 'OktaSignIn::Success'
Dimensions:
- Name: Stage
Value: !Ref 'Stage'
- Name: ApiMode
Value: identity-gateway
Period: 1200
Stat: Sum
Unit: Count
ReturnData: false
- Id: oktaIdxSignInCount
MetricStat:
Metric:
Namespace: Gateway
MetricName: 'OktaIdxSignIn::Success'
Dimensions:
- Name: Stage
Value: !Ref 'Stage'
- Name: ApiMode
Value: identity-gateway
Period: 1200
Stat: Sum
Unit: Count
ReturnData: false
ComparisonOperator: LessThanThreshold
Threshold: 1
EvaluationPeriods: 1
AlarmActions:
- !Ref 'TopicSendEmail'
InsufficientDataActions:
- !Ref 'TopicSendEmail'
RegisterInactivityAlarm:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
AlarmName: !Sub
- '${Priority} - ${App} ${Stage} has had no new registrations in the last hour'
- Priority: !FindInMap [StageVariables, AlarmPriorities, P1]
AlarmDescription: No one has successfully registered in the last hour.
Metrics:
- Id: totalRegistrationCount
Expression: oktaIdxRegistrationCount + oktaRegistrationCount
Label: 'Total registrations in Okta Classic and Okta IDX'
- Id: oktaIdxRegistrationCount
MetricStat:
Metric:
Namespace: Gateway
MetricName: 'OktaIDXRegister::Success'
Dimensions:
- Name: Stage
Value: !Ref 'Stage'
- Name: ApiMode
Value: identity-gateway
Period: 3600
Stat: Sum
Unit: Count
ReturnData: false
- Id: oktaRegistrationCount
MetricStat:
Metric:
Namespace: Gateway
MetricName: 'OktaRegistration::Success'
Dimensions:
- Name: Stage
Value: !Ref 'Stage'
- Name: ApiMode
Value: identity-gateway
Period: 3600
Stat: Sum
Unit: Count
ReturnData: false
ComparisonOperator: LessThanThreshold
Threshold: 1
EvaluationPeriods: 1
AlarmActions:
- !Ref 'TopicSendEmail'
InsufficientDataActions:
- !Ref 'TopicSendEmail'
OAuthAuthenticationCallbackInactivityAlarm:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
AlarmName: !Sub
- '${Priority} - ${App} ${Stage} has had no success OAuth Authorization code flow callbacks for Authentication in the last 20 minutes'
- Priority: !FindInMap [StageVariables, AlarmPriorities, P1]
AlarmDescription: No one has successfully completed OAuth Authorization code flow callbacks for Authentication in the last 20 minutes.
Metrics:
- Id: totalOAuthAuthenticationCallbackCount
Expression: oktaOAuthAuthenticationCallbackCount
Label: 'Total OAuth Authorization Callbacks for Authentication in Okta'
- Id: oktaOAuthAuthenticationCallbackCount
MetricStat:
Metric:
Namespace: Gateway
MetricName: 'OAuthAuthenticationCallback::Success'
Dimensions:
- Name: Stage
Value: !Ref 'Stage'
- Name: ApiMode
Value: identity-gateway
Period: 1200
Stat: Sum
Unit: Count
ReturnData: false
ComparisonOperator: LessThanThreshold
Threshold: 1
EvaluationPeriods: 1
AlarmActions:
- !Ref 'TopicSendEmail'
InsufficientDataActions:
- !Ref 'TopicSendEmail'
OAuthApplicationCallbackInactivityAlarm:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
AlarmName: !Sub
- '${Priority} - ${App} ${Stage} has had no success OAuth Authorization code flow callbacks for internal Gateway routes in the last 1 hour'
- Priority: !FindInMap [StageVariables, AlarmPriorities, P1]
AlarmDescription: No one has successfully completed OAuth Authorization code flow callbacks for internal Gateway routes in the last 1 hour.
Metrics:
- Id: totalOAuthApplicationCallbackCount
Expression: oktaOAuthApplicationCallbackCount
Label: 'Total OAuth Authorization Callbacks for internal Gateway routes in Okta'
- Id: oktaOAuthApplicationCallbackCount
MetricStat:
Metric:
Namespace: Gateway
MetricName: 'OAuthApplicationCallback::Success'
Dimensions:
- Name: Stage
Value: !Ref 'Stage'
- Name: ApiMode
Value: identity-gateway
Period: 3600
Stat: Sum
Unit: Count
ReturnData: false
ComparisonOperator: LessThanThreshold
Threshold: 1
EvaluationPeriods: 1
AlarmActions:
- !Ref 'TopicSendEmail'
InsufficientDataActions:
- !Ref 'TopicSendEmail'
DeletionInactivityAlarm:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
AlarmName: !Sub
- '${Priority} - ${App} ${Stage} has had no success self service user deletion in the last 6 hours'
- Priority: !FindInMap [StageVariables, AlarmPriorities, P2]
AlarmDescription: No one has successfully deleted their account in the last 6 hours.
Metrics:
- Id: totalDeletionCount
Expression: deleteAccountCount
Label: 'Total self service user deletions'
- Id: deleteAccountCount
MetricStat:
Metric:
Namespace: Gateway
MetricName: 'OAuthDeleteCallback::Success'
Dimensions:
- Name: Stage
Value: !Ref 'Stage'
- Name: ApiMode
Value: identity-gateway
Period: 21600
Stat: Sum
Unit: Count
ReturnData: false
ComparisonOperator: LessThanThreshold
Threshold: 1
EvaluationPeriods: 1
AlarmActions:
- !Ref 'TopicSendEmail'
InsufficientDataActions:
- !Ref 'TopicSendEmail'
UnsubscribeAllInactivityAlarm:
Type: AWS::CloudWatch::Alarm
Condition: IsProd
Properties:
AlarmName: !Sub
- '${Priority} - ${App} ${Stage} has had successful no unsubscribe all from email clients in the last hour'
- Priority: !FindInMap [StageVariables, AlarmPriorities, P2]
AlarmDescription: 'No one has successfully unsubscribed all from email clients in the last hour.'
Metrics:
- Id: totalUnsubscribeAllCount
Expression: unsubscribeAllCount
Label: 'Total unsubscribe all'
- Id: unsubscribeAllCount
MetricStat:
Metric:
Namespace: Gateway
MetricName: 'UnsubscribeAll::Success'
Dimensions:
- Name: Stage
Value: !Ref 'Stage'
- Name: ApiMode
Value: identity-gateway
Period: 3600
Stat: Sum
Unit: Count
ReturnData: false
ComparisonOperator: LessThanThreshold
Threshold: 1
EvaluationPeriods: 1
AlarmActions:
- !Ref 'TopicSendEmail'
InsufficientDataActions:
- !Ref 'TopicSendEmail'