사용하지 않는 Amazon EC2 보안 그룹을 찾는 방법
고아 보안 그룹을 확인하여 정리하고 제거 할 수있는 방법을 찾으려고합니다. 사용하지 않는 보안 그룹을 검색하는 방법을 아는 사람이 있습니까?
콘솔 또는 명령 줄 도구를 통해 작동합니다 (Linux 및 OSX 시스템에서 명령 줄 도구 실행).
참고 : 이것은 RDS와 같은 다른 서비스가 아닌 EC2의 보안 사용만을 고려합니다. EC2 외부에서 사용되는 보안 그룹을 포함하려면 더 많은 작업을 수행해야합니다. 좋은 점은 다른 서비스와 연결된 하나를 놓친 경우 활성 보안 그룹을 쉽게 삭제할 수 없다는 것입니다 (가능하지 않을 수도 있음).
최신 AWS CLI 도구를 사용하여 필요한 것을 쉽게 얻을 수있는 방법을 찾았습니다.
먼저 모든 보안 그룹 목록을 가져옵니다.
aws ec2 describe-security-groups --query 'SecurityGroups[*].GroupId' --output text | tr '\t' '\n'
그런 다음 인스턴스에 연결된 모든 보안 그룹을 sort
가져온 다음 다음으로 파이프됩니다 uniq
.
aws ec2 describe-instances --query 'Reservations[*].Instances[*].SecurityGroups[*].GroupId' --output text | tr '\t' '\n' | sort | uniq
그런 다음 그것을 모아 두 목록을 비교하고 마스터 목록에서 사용되지 않는 것을 확인하십시오.
comm -23 <(aws ec2 describe-security-groups --query 'SecurityGroups[*].GroupId' --output text | tr '\t' '\n'| sort) <(aws ec2 describe-instances --query 'Reservations[*].Instances[*].SecurityGroups[*].GroupId' --output text | tr '\t' '\n' | sort | uniq)
EC2 콘솔에서 모든 보안 그룹을 선택한 다음 작업-> 보안 그룹 삭제를 누르면 인스턴스, 다른 보안 그룹 또는 네트워크 인터페이스에 연결된 보안 그룹을 삭제할 수 없음을 알리는 팝업이 나타납니다. 삭제할 수있는 보안 그룹이 나열됩니다. 즉, 사용되지 않는 보안 그룹 :)
연결된 인스턴스 수에 대해 보안 그룹을 나열하기 위해 boto (AWS 용 Python SDK)로 작성된 샘플 코드입니다.
이 논리를 사용하여 명령 줄에서도 동일한 결과를 얻을 수 있습니다.
Boto 코드
import boto
ec2 = boto.connect_ec2()
sgs = ec2.get_all_security_groups()
for sg in sgs:
print sg.name, len(sg.instances())
산출
Security-Group-1 0
Security-Group-2 1
Security-Group-3 0
Security-Group-4 3
약 1 년 동안 감사를받지 않고 사용한 후 AWS EC2 보안 그룹을 감사하고 사용하지 않는 레거시 그룹을 정리해야한다는 것을 알게되었습니다.
이것은 웹 GUI를 통해 수행하기 어려운 작업 이었으므로 작업을 더 쉽게 만들기 위해 AWS CLI를 살펴 보았습니다. StackOverflow에서이 작업을 수행하는 방법에 대한 시작을 찾았지만 아직 완료되지 않았습니다. 그래서 저는 제 대본을 쓰기로했습니다. AWS CLI, MySQL 및 일부 "Bash-foo"를 사용하여 다음을 수행했습니다.
모든 EC2 보안 그룹 목록을 가져옵니다. 나는 localhost의 aws_security_groups라는 MySQL 데이터베이스에있는“groups”라는 테이블에 group-id, group-name 및 설명을 저장합니다. 발견 된 총 그룹 수가 사용자에게보고됩니다.
다음 서비스 각각에 연결된 모든 보안 그룹의 목록을 가져 와서 테이블에서 제외합니다. EC2 Istances EC2 Elastic Load Balancers AWS RDS 인스턴스 AWS OpsWorks (Amazon별로 제거 할 수 없음) 기본 보안 그룹 (삭제할 수 없음) ) ElastiCache
각 서비스에 대해 제외가 완료된 후 테이블에 남아있는 그룹 수를보고합니다.
- 마지막으로 남은 그룹에 대한 그룹 ID, 그룹 이름 및 설명을 표시합니다. 감사 및 / 또는 삭제해야하는 "사용되지 않는"그룹입니다. 인스턴스와 ELB (Elastic Load Balancer) 사이의 SG가 종종 서로를 참조한다는 것을 발견했습니다. 상호 참조를 제거하고 보안 그룹을 삭제하기 전에 실제로 사용되고 있지 않은지 확인하기 위해 몇 가지 수동 조사를 수행하는 것이 가장 좋습니다. 그러나 내 스크립트는 적어도 이것을 관리 할 수있는 것으로 축소합니다.
참고 : 1. MySQL 호스트, 사용자 이름 및 암호를 저장할 파일을 만들고 $ DBCONFIG 변수를 지정합니다. 다음과 같이 구성되어야합니다.
[mysql]
host=your-mysql-server-host.com
user=your-mysql-user
password=your-mysql-user-password
- 원하는 경우 데이터베이스 이름을 변경할 수 있습니다. 스크립트에서 $ DB 변수를 변경해야합니다.
이 기능이 유용하거나 의견, 수정 또는 개선 사항이 있으면 알려주십시오.
다음은 스크립트입니다.
#!/bin/bash
# Initialize Variables
DBCONFIG="--defaults-file=mysql-defaults.cnf"
DB="aws_security_groups"
SGLOOP=0
EC2LOOP=0
ELBLOOP=0
RDSLOOP=0
DEFAULTLOOP=0
OPSLOOP=0
CACHELOOP=0
DEL_GROUP=""
# Function to report back # of rows
function Rows {
ROWS=`echo "select count(*) from groups" | mysql $DBCONFIG --skip-column-names $DB`
# echo -e "Excluding $1 Security Groups.\nGroups Left to audit: "$ROWS
echo -e $ROWS" groups left after Excluding $1 Security Groups."
}
# Empty the table
echo -e "delete from groups where groupid is not null" | mysql $DBCONFIG $DB
# Get all Security Groups
aws ec2 describe-security-groups --query "SecurityGroups[*].[GroupId,GroupName,Description]" --output text > /tmp/security_group_audit.txt
while IFS=$'\t' read -r -a myArray
do
if [ $SGLOOP -eq 0 ];
then
VALUES="(\""${myArray[0]}"\",\""${myArray[1]}"\",\""${myArray[2]}"\")"
else
VALUES=$VALUES",(\""${myArray[0]}"\",\""${myArray[1]}"\",\""${myArray[2]}"\")"
fi
let SGLOOP="$SGLOOP + 1"
done < /tmp/security_group_audit.txt
echo -e "insert into groups (groupid, groupname, description) values $VALUES" | mysql $DBCONFIG $DB
echo -e $SGLOOP" security groups total."
# Exclude Security Groups assigned to Instances
for groupId in `aws ec2 describe-instances --output json | jq -r ".Reservations[].Instances[].SecurityGroups[].GroupId" | sort | uniq`
do
if [ $EC2LOOP -eq 0 ];
then
DEL_GROUP="'$groupId'"
else
DEL_GROUP=$DEL_GROUP",'$groupId'"
fi
let EC2LOOP="$EC2LOOP + 1"
done
echo -e "delete from groups where groupid in ($DEL_GROUP)" | mysql $DBCONFIG $DB
Rows "EC2 Instance"
DEL_GROUP=""
# Exclude groups assigned to Elastic Load Balancers
for elbGroupId in `aws elb describe-load-balancers --output json | jq -c -r ".LoadBalancerDescriptions[].SecurityGroups" | tr -d "\"[]\"" | sort | uniq`
do
if [ $ELBLOOP -eq 0 ];
then
DEL_GROUP="'$elbGroupId'"
else
DEL_GROUP=$DEL_GROUP",'$elbGroupId'"
fi
let ELBLOOP="$ELBLOOP + 1"
done
echo -e "delete from groups where groupid in ($DEL_GROUP)" | mysql $DBCONFIG $DB
Rows "Elastic Load Balancer"
DEL_GROUP=""
# Exclude groups assigned to RDS
for RdsGroupId in `aws rds describe-db-instances --output json | jq -c -r ".DBInstances[].VpcSecurityGroups[].VpcSecurityGroupId" | sort | uniq`
do
if [ $RDSLOOP -eq 0 ];
then
DEL_GROUP="'$RdsGroupId'"
else
DEL_GROUP=$DEL_GROUP",'$RdsGroupId'"
fi
let RDSLOOP="$RDSLOOP + 1"
done
echo -e "delete from groups where groupid in ($DEL_GROUP)" | mysql $DBCONFIG $DB
Rows "RDS Instances"
DEL_GROUP=""
# Exclude groups assigned to OpsWorks
for OpsGroupId in `echo -e "select groupid from groups where groupname like \"AWS-OpsWorks%\"" | mysql $DBCONFIG $DB`
do
if [ $OPSLOOP -eq 0 ];
then
DEL_GROUP="'$OpsGroupId'"
else
DEL_GROUP=$DEL_GROUP",'$OpsGroupId'"
fi
let OPSLOOP="$OPSLOOP + 1"
done
echo -e "delete from groups where groupid in ($DEL_GROUP)" | mysql $DBCONFIG $DB
Rows "OpsWorks"
DEL_GROUP=""
# Exclude default groups (can't be deleted)
for DefaultGroupId in `echo -e "select groupid from groups where groupname like \"default%\"" | mysql $DBCONFIG $DB`
do
if [ $DEFAULTLOOP -eq 0 ];
then
DEL_GROUP="'$DefaultGroupId'"
else
DEL_GROUP=$DEL_GROUP",'$DefaultGroupId'"
fi
let DEFAULTLOOP="$DEFAULTLOOP + 1"
done
echo -e "delete from groups where groupid in ($DEL_GROUP)" | mysql $DBCONFIG $DB
Rows "Default"
DEL_GROUP=""
# Exclude Elasticache groups
for CacheGroupId in `aws elasticache describe-cache-clusters --output json | jq -r ".CacheClusters[].SecurityGroups[].SecurityGroupId" | sort | uniq`
do
if [ $CACHELOOP -eq 0 ];
then
DEL_GROUP="'$CacheGroupId'"
else
DEL_GROUP=$DEL_GROUP",'$CacheGroupId'"
fi
let CACHELOOP="$CACHELOOP + 1"
done
echo -e "delete from groups where groupid in ($DEL_GROUP)" | mysql $DBCONFIG $DB
Rows "ElastiCache"
# Display Security Groups left to audit / delete
echo "select * from groups order by groupid" | mysql $DBCONFIG $DB | sed 's/groupid\t/groupid\t\t/'
그리고 여기 데이터베이스를 만드는 SQL이 있습니다.
-- MySQL dump 10.13 Distrib 5.5.41, for debian-linux-gnu (x86_64)
--
-- Host: localhost Database: aws_security_groups
-- ------------------------------------------------------
-- Server version 5.5.40-log
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `groups`
--
DROP TABLE IF EXISTS `groups`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `groups` (
`groupid` varchar(12) DEFAULT NULL,
`groupname` varchar(200) DEFAULT NULL,
`description` varchar(200) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `groups`
--
LOCK TABLES `groups` WRITE;
/*!40000 ALTER TABLE `groups` DISABLE KEYS */;
/*!40000 ALTER TABLE `groups` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2015-01-27 16:07:44
node.js AWS SDK를 사용하여 AWS에서 사용중인 보안 그룹을 삭제하는 것을 허용하지 않음을 확인할 수 있습니다. 나는 단순히 모든 그룹을 삭제하려고 시도하고 오류를 정상적으로 처리하는 스크립트를 작성했습니다. 이것은 클래식 및 최신 VPC에서 작동합니다. 오류 메시지는 아래에서 볼 수 있습니다.
Err { [DependencyViolation: resource sg-12345678 has a dependent object]
message: 'resource sg-12345678 has a dependent object',
code: 'DependencyViolation',
time: Mon Dec 07 2015 12:12:43 GMT-0500 (EST),
statusCode: 400,
retryable: false,
retryDelay: 30 }
현재 인스턴스가없는 보안 그룹 의 그룹 ID와 이름 만 인쇄하는 boto 예제 입니다.
또한 관심있는 지역을 지정하는 방법도 보여줍니다.
import boto
import boto.ec2
EC2_REGION='ap-southeast-2'
ec2region = boto.ec2.get_region(EC2_REGION)
ec2 = boto.connect_ec2(region=ec2region)
sgs = ec2.get_all_security_groups()
for sg in sgs:
if len(sg.instances()) == 0:
print ("{0}\t{1}".format(sg.id, sg.name))
To confirm which security groups are still being used you should reverse or remove the if len(sg.instances()) == 0
test and print the len(sg.instances())
value out.
E.g.
print ("{0}\t{1}\t{2} instances".format(sg.id, sg.name, len(sg.instances())))
Among other functions, both ScoutSuite and Prowler report unused EC2 Security Groups. Both are open source.
To the SGs attached to the network interfaces:
By name:
aws ec2 describe-network-interfaces --output text --query NetworkInterfaces[*].Groups[*].GroupName | tr -d '\r' | tr "\t" "\n" | sort | uniq
By id:
aws ec2 describe-network-interfaces --output text --query NetworkInterfaces[*].Groups[*].GroupId | tr -d '\r' | tr "\t" "\n" | sort | uniq
There's a tool in the AWS marketplace that makes this a lot easier. It shows you which groups are attached/detached for easy deletion, but it also compares your VPC Flow Logs against the security group rules and shows you which SG rules are in use or unused. AWS posted an ELK-stack solution to do this, but it was ridiculously complex.
Here's the tool, and a disclaimer that I worked on it. But I hope you all find it pertinent: https://www.piasoftware.net/single-post/2018/04/24/VIDEO-Watch-as-we-clean-up-EC2-security-groups-in-just-a-few-minutes
Unfortunately the chosen answer is not as accurate as I need (I've tried to investigate the why, but I've preferred to implement it).
If I check ALL NetworkInterfaces
, looking for attachments to any SecurityGroup
, It gets me partial results. If I check only on EC2Instances
, it gets me back partial results as well.
So that's my approach to the problem:
- I get ALL EC2 SecurityGroups ->
all_secgrp
- I get ALL EC2 Instances ->
all_instances
- For each Instance, I get all SecurityGroups attached to it
- I remove from all_secgrp each of these SecurityGroup (because attached)
- For each SecurityGroup, I check an association with any NetworkInterfaces (using the
filter
function and filtering using thatsecurity-group-id
)- IF no association is found, I remove the security-group from
all_secgrp
- IF no association is found, I remove the security-group from
Attached you can see a snippet of code. Don't complain for efficiency, but try to optimize it if you want.
all_secgrp = list(ec2_connector.security_groups.all())
all_instances = ec2_connector.instances.all()
for single_instance in all_instances:
instance_secgrp = ec2_connector.Instance(single_instance.id).security_groups
for single_sec_grp in instance_secgrp:
if ec2.SecurityGroup(id=single_sec_grp['GroupId']) in all_secgrp:
all_secgrp.remove(ec2.SecurityGroup(id=single_sec_grp['GroupId']))
all_secgrp_detached_tmp = all_secgrp[:]
for single_secgrp in all_secgrp_detached_tmp:
try:
print(single_secgrp.id)
if len(list(ec2_connector.network_interfaces.filter(Filters=[{'Name': 'group-id', 'Values': [single_secgrp.id]}]))) > 0:
all_secgrp.remove(single_secgrp)
except Exception:
all_secgrp.remove(single_secgrp)
return all_secgrp_detached
This is a difficult problem, if you have security groups that reference other security groups in the rules. If so, you'll have to resolve DependencyErrors, which is not trivial.
If you are only using IP addresses, then this solution will work, after you create a boto3 client:
# pull all security groups from all vpcs in the given profile and region and save as a set
all_sgs = {sg['GroupId'] for sg in client.describe_security_groups()['SecurityGroups']}
# create a new set for all of the security groups that are currently in use
in_use = set()
# cycle through the ENIs and add all found security groups to the in_use set
for eni in client.describe_network_interfaces()['NetworkInterfaces']:
for group in eni['Groups']:
in_use.add(group['GroupId'])
unused_security_groups = all_sgs - in_use
for security_group in unused_security_groups:
try:
response = client.delete_security_group(GroupId=security_group)
except ClientError as e:
if e.response['Error']['Code'] == 'DependencyViolation':
print('EC2/Security Group Dependencies Exist')
else:
print('Unexpected error: {}'.format(e))
참고URL : https://stackoverflow.com/questions/24685508/how-to-find-unused-amazon-ec2-security-groups
'development' 카테고리의 다른 글
Xcode에서 iOS 시뮬레이터를 시작하고 검은 색 화면이 나타난 후 Xcode가 중단되고 작업을 중지 할 수 없음 (0) | 2020.10.26 |
---|---|
보기 또는 해당 마스터가 없거나 검색된 위치를 지원하는보기 엔진이 없습니다. (0) | 2020.10.26 |
앱이 디버그에서 실행될 때 Firebase 오류보고를 비활성화하는 방법은 무엇입니까? (0) | 2020.10.26 |
값 또는 참조로 std :: string 전달 (0) | 2020.10.26 |
'+ entityForName : nil은 합법적 인 NSManagedObjectContext 매개 변수가 아닙니다-핵심 데이터 (0) | 2020.10.26 |