Подтвердить что ты не робот

Как найти Неиспользуемые группы безопасности Amazon EC2

Я пытаюсь найти способ определения сиротских групп безопасности, чтобы я мог очистить и избавиться от них. Кто-нибудь знает способ обнаружения неиспользуемых групп безопасности.

Будет работать либо через консоль, либо с помощью средств командной строки (запуск инструментов командной строки на машинах Linux и OSX).

4b9b3361

Ответ 1

Примечание. Это относится только к использованию безопасности в EC2, а не к другим службам, таким как RDS. Вам нужно будет сделать больше работы, чтобы включить группы безопасности, используемые за пределами EC2. Хорошо, что вы не можете легко (возможно, даже невозможно) удалить активные группы безопасности, если вы пропустили одну связанную w/другую услугу.

Используя новый инструмент 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

Затем поместите его и сравните 2 списка и посмотрите, что не используется из главного списка:

 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)

Ответ 2

Если вы выберете все свои группы безопасности в консоли EC2, затем нажмите действия → Удалить группы безопасности, появится всплывающее окно с сообщением о том, что вы не можете удалить группы безопасности, прикрепленные к экземплярам, ​​другим группам безопасности или сетевым интерфейсам, и в нем будут перечислены группы безопасности, которые вы можете удалить; т.е. неиспользуемые группы безопасности:)

Ответ 3

Это пример кода, написанного в boto (Python SDK для AWS), чтобы перечислить группу безопасности по количеству экземпляров, с которыми она связана.

Вы можете использовать эту логику, чтобы получить то же самое в командной строке

Код 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

Ответ 4

Примерно через год неаудированного использования я счел необходимым провести аудит моих групп безопасности AWS EC2 и очистить устаревшие неиспользуемые группы.

Это была сложная задача для выполнения через веб-интерфейс, поэтому я обратился к CLI AWS, чтобы облегчить задачу. Я нашел начало, как это сделать в StackOverflow, но это было далеко не полным. Поэтому я решил написать свой собственный script. Я использовал AWS CLI, MySQL и некоторые "Bash -foo" для выполнения следующих действий:

  • Получить список всех групп безопасности EC2. Я сохраняю идентификатор группы, имя группы и описание в объявленных "группах" в базе данных MySQL, называемой aws_security_groups на локальном хосте. Сообщается об общем количестве найденных групп.

  • Получить список всех групп безопасности, связанных с каждой из следующих служб, и исключить их из таблицы: EC2 Istances EC2 эластичные балансировочные нагрузки Экземпляры AWS RDS AWS OpsWorks (не следует удалять на Amazon) Группы безопасности по умолчанию (невозможно удалить) ElastiCache

Для каждой службы я сообщаю счет количества оставшихся в таблице групп после завершения исключения.

  1. Наконец, я показываю идентификатор группы, имя группы и описание для оставшихся групп. Это "неиспользуемые" группы, которые необходимо проверять и/или удалять. Ive обнаружил, что SG между экземплярами и Elastic Load Balancers (ELB) часто ссылаются друг на друга. Лучше всего провести ручное исследование, чтобы убедиться, что они действительно не используются до удаления перекрестных ссылок и удаления групп безопасности. Но мой script, по крайней мере, рассматривает это как нечто неприемлемое.

ПРИМЕЧАНИЯ: 1. Вам нужно будет создать файл для хранения вашего хоста, имени пользователя и пароля MySQL и указать ему переменную $DBCONFIG. Он должен быть структурирован следующим образом:

[mysql]
host=your-mysql-server-host.com
user=your-mysql-user
password=your-mysql-user-password
  1. Вы можете изменить имя базы данных, если хотите - обязательно измените переменную $DB в script

Сообщите мне, если вы найдете это полезным или у вас есть комментарии, исправления или улучшения.

Вот script.

#!/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 @[email protected]@CHARACTER_SET_CLIENT */;
/*!40101 SET @[email protected]@CHARACTER_SET_RESULTS */;
/*!40101 SET @[email protected]@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @[email protected]@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @[email protected]@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 [email protected]_TIME_ZONE */;

/*!40101 SET [email protected]_SQL_MODE */;
/*!40014 SET [email protected]_FOREIGN_KEY_CHECKS */;
/*!40014 SET [email protected]_UNIQUE_CHECKS */;
/*!40101 SET [email protected]_CHARACTER_SET_CLIENT */;
/*!40101 SET [email protected]_CHARACTER_SET_RESULTS */;
/*!40101 SET [email protected]_COLLATION_CONNECTION */;
/*!40111 SET [email protected]_SQL_NOTES */;

-- Dump completed on 2015-01-27 16:07:44

Ответ 5

Используя node.js AWS SDK, я могу подтвердить, что AWS не позволяет вам удалять группы безопасности, которые используются. Я написал script, который просто пытается удалить все группы и изящно обрабатывает ошибки. Это работает для классического и современного 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 }

Ответ 6

Пример 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))

Чтобы подтвердить, какие группы безопасности все еще используются, вы должны отменить или удалить тест if len(sg.instances()) == 0 и распечатать значение len(sg.instances()).

например.

print ("{0}\t{1}\t{2} instances".format(sg.id, sg.name, len(sg.instances())))

Ответ 7

Среди других функций ScoutSuite и Prowler сообщают о неиспользованных группах безопасности EC2. Оба с открытым исходным кодом.

Ответ 8

Для SG, подключенных к сетевым интерфейсам:

По имени:

aws ec2 describe-network-interfaces --output text --query NetworkInterfaces[*].Groups[*].GroupName | tr -d '\r' | tr "\t" "\n" | sort | uniq

По идентификатору:

aws ec2 describe-network-interfaces --output text --query NetworkInterfaces[*].Groups[*].GroupId | tr -d '\r' | tr "\t" "\n" | sort | uniq

Ответ 9

Там есть инструмент на рынке AWS, который делает это намного проще. Он показывает, какие группы прикреплены/отсоединены для удобства удаления, но также сравнивает ваши протоколы потоков VPC с правилами группы безопасности и показывает, какие правила SG используются или не используются. AWS разместила решение ELK-стека для этого, но это было смешно сложным.

Вот инструмент и отказ от ответственности, над которым я работал. Но я надеюсь, что вы все это сочтете нужным: https://www.piasoftware.net/single-post/2018/04/24/VIDEO-Watch-as-we-clean-up-EC2-security-groups-in-just -несколько минут

Ответ 10

К сожалению, выбранный ответ не так точен, как мне нужно (я попытался выяснить причину, но я предпочел его реализовать).
Если я проверю ALL NetworkInterfaces, ищет вложения в любую SecurityGroup, он получает частичные результаты. Если я проверю только на EC2Instances, он также возвращает мне частичные результаты.

Так что мой подход к проблеме:

  1. Я получаю ВСЕ EC2 SecurityGroups → all_secgrp
  2. Я получаю ВСЕ экземпляры EC2 → all_instances
  3. Для каждого экземпляра я подключаю к нему все SecurityGroups
    1. Я удаляю из all_secgrp каждую из этих SecurityGroup (потому что прикреплен)
  4. Для каждой SecurityGroup я проверяю связь с любыми сетевыми интерфейсами (используя функцию filter и фильтрацию с использованием этого security-group-id)
    1. Если связь не найдена, я all_secgrp группу безопасности из all_secgrp

В приложении вы можете увидеть фрагмент кода. Не жалуйтесь на эффективность, но старайтесь оптимизировать его, если хотите.

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  

Ответ 11

Это сложная проблема, если у вас есть группы безопасности, которые ссылаются на другие группы безопасности в правилах. Если это так, вам придется решать DependencyErrors, что не является тривиальным.

Если вы используете только IP-адреса, то это решение будет работать после создания клиента boto3:

# 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))

Ответ 12

Самый простой способ обнаружить неиспользуемые группы безопасности в данном VPC - это использовать aws-cli с опцией описания-stale-security-groups.

Дополнительную информацию см. В следующей документации.

https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-stale-security-groups.html

Надеюсь это поможет.