it-swarm.com.ru

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

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

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

62
Ray

Примечание: это касается только использования безопасности в EC2, а не других служб, таких как RDS. Вам нужно будет проделать дополнительную работу, чтобы включить группы безопасности, используемые за пределами 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

Затем соедините его, сравните 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)
66
Ray

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

35
NLail

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

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

Код Бото

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
21
Naveen Vijay

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

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

  1. Получить список всех групп безопасности EC2 . Я храню идентификатор группы, имя группы и описание в таблице с именем «groups» в базе данных MySQL с именем aws_security_groups на локальном хосте. Общее количество найденных групп сообщается пользователю.

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

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

  1. Наконец, я отображаю идентификатор группы, имя группы и описание для оставшихся групп. Это «неиспользуемые» группы, которые должны быть проверены и/или удалены. Я обнаружил, что SG между экземплярами и эластичными балансировщиками нагрузки (ELB) часто ссылаются друг на друга. Перед удалением перекрестных ссылок и удалением групп безопасности рекомендуется провести некоторое ручное расследование, чтобы убедиться, что они действительно не используются. Но мой сценарий по крайней мере сводит это к чему-то более управляемому.

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

[mysql]
Host=your-mysql-server-Host.com
user=your-mysql-user
password=your-mysql-user-password
  1. Вы можете изменить имя базы данных, если хотите - обязательно измените переменную $ 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 @[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
2
user2962402

Используя AWS SDK node.js, я могу подтвердить, что 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 }
2
Michael Connor

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

1
Nan Zhong

Пример 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())))
1
Akira Kurogane

Это сложная проблема, если у вас есть группы безопасности, которые ссылаются на другие группы безопасности в правилах. Если это так, вам придется устранить 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))
0
PythonNoob

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

Вот мой подход к проблеме: 

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

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

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

0
rajat banerjee