Misconfigured security groups are one of the most common security issues in AWS environments. During development or troubleshooting, itโs easy to temporarily allow SSH access from ๐ฌ.๐ฌ.๐ฌ.๐ฌ/๐ฌ and then forget to remove it. Even a small oversight like this can expose EC2 instances to unnecessary risk.
To solve this problem, I built an automated remediation workflow using ๐๐๐ ๐๐จ๐ง๐๐ข๐ , ๐๐ฆ๐๐ณ๐จ๐ง ๐๐ฏ๐๐ง๐ญ๐๐ซ๐ข๐๐ ๐, ๐๐ง๐ ๐๐๐ ๐๐๐ฆ๐๐๐. Instead of relying on manual reviews, the solution continuously monitors security group changes, detects when SSH is opened to the internet, and automatically removes the insecure rule within about 90 seconds.
๐๐๐๐ ๐: ๐๐ซ๐๐๐ญ๐ ๐ ๐๐๐๐ฎ๐ซ๐ข๐ญ๐ฒ ๐๐ซ๐จ๐ฎ๐ฉ
To demonstrate the remediation workflow, I first created a new security group named tester-remediation-security-group. Initially, I didnโt configure any inbound rules because the goal was to gradually introduce the insecure SSH rule later and observe how AWS Config detects it.
The default outbound rule allowing all traffic ๐ฌ.๐ฌ.๐ฌ.๐ฌ/๐ฌ was left unchanged, as it doesnโt affect this demonstration.
๐๐ญ๐๐ฉ ๐: ๐๐ง๐๐๐ฅ๐ ๐๐๐ ๐๐จ๐ง๐๐ข๐
Since AWS Config continuously monitors resource configurations, it must be enabled before creating any compliance rules.
If youโre setting this up for the first time, navigate to the AWS Config console and complete the initial setup by selecting the recommended configuration options. AWS Config will automatically create the required IAM role and begin recording supported AWS resources.
Once the setup is complete, AWS Config starts tracking configuration changes across your AWS account.
๐๐ญ๐๐ฉ ๐: ๐๐ซ๐๐๐ญ๐ ๐ ๐๐๐ฐ ๐๐จ๐ง๐๐ข๐ ๐๐ฎ๐ฅ๐
After enabling AWS Config, navigate to the Rules section and choose Add rule.
AWS provides several managed compliance rules out of the box. For this project, I selected the AWS managed rule ๐ซ๐๐ฌ๐ญ๐ซ๐ข๐๐ญ๐๐-๐ฌ๐ฌ๐ก, which is specifically designed to detect security groups that allow SSH access from unrestricted IP addresses such as ๐.๐.๐.๐/๐.
๐๐ญ๐๐ฉ ๐: ๐๐จ๐ง๐๐ข๐ ๐ฎ๐ซ๐ ๐ญ๐ก๐ ๐๐ฎ๐ฅ๐
Next, I configured the rule by providing a suitable name and description while keeping the default evaluation settings.
The ๐ซ๐๐ฌ๐ญ๐ซ๐ข๐๐ญ๐๐-๐ฌ๐ฌ๐ก rule evaluates all security groups in the account and checks whether port 22 (SSH) is exposed to the public internet. If such a rule exists, AWS Config marks the resource as ๐๐๐_๐๐๐๐๐๐๐๐๐.
๐๐ญ๐๐ฉ ๐: ๐๐๐ฏ๐ข๐๐ฐ ๐๐ง๐ ๐๐ซ๐๐๐ญ๐
Before creating the rule, I reviewed all the configuration details to ensure everything was correct.
Once verified, I created the rule, allowing AWS Config to begin evaluating existing security groups against the compliance policy.
๐๐ญ๐๐ฉ ๐: ๐๐ฎ๐ฅ๐ ๐๐ฎ๐๐๐๐ฌ๐ฌ๐๐ฎ๐ฅ๐ฅ๐ฒ ๐๐ซ๐๐๐ญ๐๐
After the rule was created successfully, it appeared in the AWS Config Rules dashboard.
At this stage, AWS Config automatically started evaluating all recorded security groups. Since evaluations are not always immediate, it may take a short time before the compliance results are displayed.
๐๐ญ๐๐ฉ ๐: ๐๐จ๐ฆ๐ฉ๐ฅ๐ข๐๐ง๐๐ ๐๐ฏ๐๐ฅ๐ฎ๐๐ญ๐ข๐จ๐ง
After waiting for a couple of minutes, AWS Config completed its evaluation.
The dashboard now showed the restricted-ssh rule with a ๐๐๐_๐๐๐๐๐๐๐๐๐ status, indicating that it had detected security groups violating the rule. The compliance summary also displayed the affected resources, confirming that AWS Config had successfully identified the security issue.
๐๐ญ๐๐ฉ ๐: ๐๐ซ๐๐๐ญ๐ ๐ญ๐ก๐ ๐๐๐ฆ๐๐๐ ๐ ๐ฎ๐ง๐๐ญ๐ข๐จ๐ง
The next step is to create an AWS Lambda function that will automatically remediate non-compliant security groups.
Navigate to the AWS Lambda console and choose Create function. Select Author from scratch, provide a suitable function name such as security-group-ssh-remediation, and choose Python 3.13 as the runtime. This function will be responsible for removing any SSH rule that allows unrestricted public access.
๐๐ญ๐๐ฉ ๐: ๐๐ฆ๐ฉ๐ฅ๐๐ฆ๐๐ง๐ญ ๐ญ๐ก๐ ๐๐๐ฆ๐๐๐ข๐๐ญ๐ข๐จ๐ง ๐๐จ๐ ๐ข๐
Once the Lambda function has been created, replace the default code with the remediation logic shown below.
The function is designed to receive the compliance event generated by AWS Config through Amazon EventBridge. It identifies the non-compliant security group and automatically revokes the inbound SSH rule that allows access from 0.0.0.0/0.
import json, boto3
ec2 = boto3.client("ec2")
def lambda_handler(event, context):
print("Event:", json.dumps(event))
detail = event["detail"]
if detail.get("newEvaluationResult", {}).get("complianceType") != "NON_COMPLIANT":
return {"status": "skipped - compliant"}
sg_id = detail["resourceId"]
sg = ec2.describe_security_groups(GroupIds=[sg_id])["SecurityGroups"][0]
revoked = []
for perm in sg["IpPermissions"]:
if perm.get("FromPort") == 22 and perm.get("ToPort") == 22:
bad = [r for r in perm.get("IpRanges", []) if r.get("CidrIp") == "0.0.0.0/0"]
if bad:
ec2.revoke_security_group_ingress(
GroupId=sg_id,
IpPermissions=[{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"IpRanges": bad
}]
)
revoked.append(sg_id)
print("Revoked from:", revoked)
return {"revoked": revoked}
Step 10: Configure Lambda Permissions
After implementing the function, the next step is to configure its execution permissions.
Open the Configuration tab of the Lambda function and navigate to the Permissions section. The Lambda function requires an IAM execution role with the necessary permissions to inspect and modify security groups.
Step 11: Create an IAM Policy
Create a new IAM policy that grants the Lambda function permission to manage security group rules.
The policy should allow the following EC2 actions:
โข ec2:DescribeSecurityGroups
โข ec2:RevokeSecurityGroupIngress
These permissions enable the Lambda function to identify the affected security group and remove the insecure SSH rule automatically.
Step 12: Attach and Name the Policy
After defining the policy, give it a meaningful name such as esc-revoke-policy.
Attach this policy to the Lambda execution role (security-group-ssh-remediation-role) so that the function has the required permissions to perform the remediation whenever it is invoked.
Step 13: Open Amazon EventBridge
With the Lambda function ready, the next step is to configure Amazon EventBridge.
Navigate to the Amazon EventBridge console. EventBridge will listen for compliance state changes generated by AWS Config and trigger the Lambda function whenever a security group becomes non-compliant.
Step 14: Create an EventBridge Rule
From the Rules section, choose Create rule.
Provide a descriptive name such as config-non-compliant-ssh-rule and use the Advanced (Custom Pattern) option. This allows the rule to match only the AWS Config compliance events that are relevant to this remediation workflow.
Step 15: Configure the Event Pattern
In the Event Pattern section, select the Custom Pattern (JSON Editor) option and paste the JSON event pattern shown below.
This pattern filters events generated by AWS Config and ensures that the Lambda function is invoked only when the restricted-ssh Config rule reports a NON_COMPLIANT resource.
Here is the policy
{
"source": ["aws.config"],
"detail-type": ["Config Rules Compliance Change"],
"detail": {
"messageType": ["ComplianceChangeNotification"],
"configRuleName": ["restricted-ssh"],
"newEvaluationResult": {
"complianceType": ["NON_COMPLIANT"]
}
}
}
Step 16: Configure the EventBridge Target
After defining the event pattern, the next step is to configure the target that should be invoked whenever a matching event occurs.
Select AWS Service as the target type and choose Lambda Function as the target. From the list of available functions, select SG-SSH-remediator. For permissions, keep the recommended option, Create a new role for this specific resource, which allows EventBridge to invoke the Lambda function securely.
Once everything is configured, proceed to create the rule.
Step 17: Verify the EventBridge Rule
After creating the rule, EventBridge displays a confirmation message indicating that the rule has been created successfully.
At this point, the automation pipeline is fully configured. AWS Config will detect compliance changes, EventBridge will capture the event, and Lambda will perform the remediation automatically.
Step 18: Test the Automation
To test the workflow, return to the previously created security group and edit the inbound rules.
Add a new inbound rule with the following configuration:
โข Type: SSH
โข Port: 22
โข Source: Anywhere (0.0.0.0/0)
This intentionally creates a security misconfiguration that should trigger the automated remediation process.
Step 19: Confirm the Security Group Change
After saving the inbound rule, verify that the SSH rule has been successfully added to the security group.
At this stage, the security group is publicly accessible over SSH, making it non-compliant with the restricted-ssh AWS Config rule.
Step 20: Automatic Remediation
Wait for approximately 30 to 90 seconds while AWS Config evaluates the resource.
After refreshing the security group, youโll notice that the SSH rule allowing 0.0.0.0/0 has been automatically removed. No manual action is requiredโthe entire remediation process is performed by the Lambda function triggered through Amazon EventBridge.
This confirms that the automation is working as expected.
Step 21: Verify the Lambda Execution
To confirm that the remediation was performed by the Lambda function, open Amazon CloudWatch Logs and navigate to the log group associated with the remediation function.
The latest log stream shows a successful execution, including a message indicating that the insecure SSH rule was revoked from the security group. These logs provide proof that the automation completed successfully.
Step 22: Validate Compliance Status
Finally, return to the AWS Config Rules dashboard and review the compliance status.
After the remediation completes, the restricted-ssh rule is evaluated again, and the affected security group is marked as COMPLIANT. This confirms that the environment has automatically returned to a secure and compliant state without requiring any manual intervention.























Top comments (0)