Cách tìm các nhóm Bảo mật Amazon EC2 không được sử dụng


93

Tôi đang cố gắng tìm cách xác định các nhóm bảo mật mồ côi để có thể dọn dẹp và loại bỏ chúng. Có ai biết một cách để phát hiện ra các nhóm bảo mật không sử dụng.

Thông qua bảng điều khiển hoặc với các công cụ dòng lệnh sẽ hoạt động (Chạy các công cụ dòng lệnh trên máy linux và OSX).


3
Vương quốc của tôi để có câu trả lời trả lời đầy đủ cho câu hỏi này, không có ngoại lệ cho các đối tượng không tồn tại lâu dài (RDS, ELB, ALB) có thể được gán SG cho chúng và không liên quan đến 'chọn tất cả, rồi xóa' cuối tuần đáng sợ -cách tiếp cận tiền sảnh. :)
Jesse Adelman

Câu trả lời:


77

Lưu ý: điều này chỉ xem xét việc sử dụng bảo mật trong EC2, không phải các dịch vụ khác như RDS. Bạn sẽ cần phải làm nhiều việc hơn để bao gồm các nhóm bảo mật được sử dụng bên ngoài EC2. Điều tốt là bạn không thể dễ dàng (thậm chí có thể không thực hiện được) xóa các nhóm bảo mật đang hoạt động nếu bạn bỏ lỡ một dịch vụ được liên kết với một dịch vụ khác.

Bằng cách sử dụng công cụ AWS CLI mới hơn, tôi đã tìm thấy một cách dễ dàng để có được những gì tôi cần:

Đầu tiên, lấy danh sách tất cả các nhóm bảo mật

aws ec2 describe-security-groups --query 'SecurityGroups[*].GroupId'  --output text | tr '\t' '\n'

Sau đó, lấy tất cả các nhóm bảo mật liên kết với một phiên bản, sau đó chuyển đến sortsau đó uniq:

aws ec2 describe-instances --query 'Reservations[*].Instances[*].SecurityGroups[*].GroupId' --output text | tr '\t' '\n' | sort | uniq

Sau đó, tập hợp nó lại với nhau và so sánh 2 danh sách và xem những gì không được sử dụng từ danh sách chính:

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)

1
@Erik Có, tôi chỉ có một vùng duy nhất và các tập lệnh AWS có vùng chính của chúng được đặt thông qua các biến môi trường. Tôi muốn xem phiên bản nhiều vùng của tập lệnh này.
Ray

1
bạn có thể muốn thêm một --filter cho vpc của bạn, do đó bạn không cần phải nhìn thấy khác vpc mặc định sg
shadowbq

2
ELB cũng có thể sử dụng một nhóm bảo mật. Lệnh này sẽ liệt kê tập hợp các ID nhóm bảo mật uniq được tham chiếu bởi các ELB trong vùng mặc định:aws elb describe-load-balancers --query 'LoadBalancerDescriptions[*].SecurityGroups[*]' --output text | tr '\t' '\n' | sort | uniq
astletron

2
Một nhóm bảo mật EC2 cũng có thể được sử dụng bởi một phiên bản RDS. Lệnh này sẽ liệt kê các ID nhóm bảo mật được sử dụng bởi các trường hợp RDS trong khu vực mặc định:aws rds describe-db-security-groups --query 'DBSecurityGroups[*].EC2SecurityGroups[*].EC2SecurityGroupId' --output text | tr '\t' '\n' | sort | uniq
aharden

2
Bạn cũng có thể sử dụng aws ec2 describe-network-interfaces --query 'NetworkInterfaces[*].Groups[*].GroupId' --output text| tr '\t' '\n' | sort | uniqđể chỉ mô tả các giao diện mạng.
Jonathan

61

Nếu bạn chọn tất cả các nhóm bảo mật của mình trong bảng điều khiển EC2, sau đó nhấn hành động -> Xóa Nhóm bảo mật, một cửa sổ bật lên sẽ xuất hiện cho bạn biết rằng bạn không thể xóa các nhóm bảo mật được đính kèm với các phiên bản, nhóm bảo mật khác hoặc giao diện mạng, và nó sẽ liệt kê các nhóm bảo mật mà bạn có thể xóa; tức là các nhóm bảo mật không được sử dụng :)


15
Mặc dù tôi phải đồng ý, sử dụng "chọn tất cả + xóa" thường không thực sự là một thói quen tốt.
Balmipour

3
Nếu bạn không chắc liệu nó có hoạt động hay không, bạn có thể tạo một nhóm bảo mật giả và đính kèm vào đó một thứ gì đó, hãy thử xóa nó đi và thấy rằng nó sẽ không cho phép bạn.
NLail

2
Bạn không cần thực sự xác nhận việc xóa, trong cửa sổ bật lên, nó sẽ hiển thị cho bạn bảng phân tích về những cái nào có thể xóa (mồ côi) và cái nào không thể. Sau đó, bạn có thể nhấn hủy và sau đó xóa những đứa trẻ mồ côi.
rjarmstrong

4
Điều tôi không hiểu là: Nếu bảng điều khiển AWS có thể cung cấp thông tin này khi bạn thực hiện điều này đáng sợ.maneuver, tại sao họ không chia sẻ cách thực hiện điều tương tự thông qua API? Nó không như thế này không phải là cái gì đó có khả năng cần thiết trong môi trường lĩnh vực nâu ...
Jesse Adelman

1
hãy dũng cảm :: làm điều đó
zanuka

29

Đây là mã mẫu được viết bằng boto (Python SDK cho AWS) để liệt kê Nhóm bảo mật dựa trên số trường hợp mà nó được liên kết.

Bạn cũng có thể sử dụng logic này để có được dòng lệnh tương tự

Mã Boto

import boto
ec2 = boto.connect_ec2()
sgs = ec2.get_all_security_groups()
for sg in sgs:
    print sg.name, len(sg.instances())

Đầu ra

Security-Group-1 0
Security-Group-2 1
Security-Group-3 0
Security-Group-4 3

Tốt đẹp và dễ dàng! Cảm ơn
Chris Koston

6
Vâng, vâng, nhưng những gì abou khuỷu tay?
Ilja

Cũng lưu ý rằng điều này chỉ bao gồm các phiên bản đang chạy. Bạn cũng không thể xóa SG được liên kết với một phiên bản đã dừng.
AgDude

6
Điều này bỏ qua các giao diện từ các dịch vụ như RDS. RDS sở hữu phiên bản, nhưng bạn sở hữu ENI. Tôi nghĩ ElasticSearch và ELB công việc tương tự và sẽ không hiển thị với kịch bản này
Rajat Banerjee

6

Sau khoảng một năm sử dụng không được kiểm tra, tôi thấy cần phải kiểm tra các nhóm bảo mật AWS EC2 của mình và xóa các nhóm cũ, không sử dụng.

Đây là một nhiệm vụ khó khăn khi thực hiện thông qua GUI web, vì vậy tôi đã tìm đến AWS CLI để thực hiện nhiệm vụ dễ dàng hơn. Tôi đã tìm thấy phần bắt đầu về cách thực hiện việc này tại StackOverflow, nhưng nó còn lâu mới hoàn thành. Vì vậy, tôi quyết định viết kịch bản của riêng mình. Tôi đã sử dụng AWS CLI, MySQL và một số "Bash-foo" để thực hiện những việc sau:

  1. Nhận danh sách tất cả các nhóm bảo mật EC2. Tôi lưu trữ id nhóm, tên nhóm và mô tả trong một tab được gọi là "nhóm" trong cơ sở dữ liệu MySQL có tên aws_security_groups trên máy chủ cục bộ. Tổng số nhóm được tìm thấy được báo cáo cho người dùng.

  2. Lấy danh sách tất cả các nhóm bảo mật được liên kết với mỗi dịch vụ sau và loại trừ chúng khỏi bảng: EC2 Istances EC2 Elastic Load Balancers AWS RDS Instances AWS OpsWorks (không nên xóa theo Amazon) Các nhóm bảo mật mặc định (Không thể xóa ) ElastiCache

Đối với mỗi dịch vụ, tôi báo cáo số lượng nhóm còn lại trong bảng sau khi loại trừ hoàn tất.

  1. Cuối cùng, tôi hiển thị id nhóm, tên nhóm và mô tả cho các nhóm còn lại. Đây là những nhóm “không sử dụng” cần được kiểm toán và / hoặc xóa. Tôi thấy rằng SG giữa các phiên bản và Cân bằng tải đàn hồi (ELB) thường tham chiếu đến nhau. Cách tốt nhất là thực hiện một số điều tra thủ công để đảm bảo chúng thực sự không được sử dụng trước khi xóa các tham chiếu chéo và xóa các nhóm bảo mật. Nhưng kịch bản của tôi ít nhất cũng biến điều này thành một thứ gì đó có thể quản lý được.

LƯU Ý: 1. Bạn sẽ muốn tạo một tệp để lưu trữ máy chủ lưu trữ MySQL, tên người dùng và mật khẩu của mình và trỏ biến $ DBCONFIG vào đó. Nó phải được cấu trúc như thế này:

[mysql]
host=your-mysql-server-host.com
user=your-mysql-user
password=your-mysql-user-password
  1. Bạn có thể thay đổi tên của cơ sở dữ liệu nếu muốn - hãy đảm bảo thay đổi biến $ DB trong tập lệnh

Hãy cho tôi biết nếu bạn thấy điều này hữu ích hoặc có bất kỳ nhận xét, sửa chữa hoặc cải tiến nào.

Đây là kịch bản.

#!/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/'

Và đây là sql để tạo cơ sở dữ liệu.

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

3

Một ví dụ boto in Group ID và Tên chỉ của nhóm bảo mật mà không có trường hợp hiện nay.

Nó cũng cho biết cách chỉ định khu vực bạn quan tâm.

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

Để xác nhận nhóm bảo mật nào vẫn đang được sử dụng, bạn nên đảo ngược hoặc xóa if len(sg.instances()) == 0kiểm tra và in len(sg.instances())giá trị ra.

Ví dụ

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

3

Sử dụng SDK AWS node.js, tôi có thể xác nhận rằng AWS không cho phép bạn xóa các nhóm bảo mật đang được sử dụng. Tôi đã viết một tập lệnh chỉ đơn giản là cố gắng xóa tất cả các nhóm và xử lý lỗi một cách duyên dáng. Điều này phù hợp với VPC cổ điển và hiện đại. Thông báo lỗi có thể được nhìn thấy bên dưới.

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 }


1

Đối với các SG được gắn với giao diện mạng:

Bằng tên:

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

Theo id:

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

0

Có một công cụ trên thị trường AWS giúp việc này dễ dàng hơn rất nhiều. Nó cho bạn biết nhóm nào được đính kèm / tách rời để dễ dàng xóa, nhưng nó cũng so sánh Nhật ký luồng VPC của bạn với các quy tắc nhóm bảo mật và cho bạn biết quy tắc SG nào đang được sử dụng hoặc không được sử dụng. AWS đã đăng một giải pháp ELK-stack để thực hiện điều này, nhưng nó phức tạp đến mức nực cười.

Đây là công cụ và tuyên bố từ chối trách nhiệm mà tôi đã làm việc trên nó. Nhưng tôi hy vọng tất cả các bạn thấy nó phù hợp: https://www.piasoftware.net/single-post/2018/04/24/VIDEO-Watch-as-we-clean-up-EC2-security-groups-in-just -một vài phút


0

Thật không may, câu trả lời đã chọn không chính xác như tôi cần (Tôi đã cố gắng điều tra lý do tại sao, nhưng tôi thích triển khai nó hơn).
Nếu tôi chọn TẤT CẢ NetworkInterfaces, tìm kiếm tệp đính kèm cho bất kỳ tệp nào SecurityGroup, Tôi sẽ nhận được một phần kết quả. Nếu tôi chỉ kiểm tra EC2Instances, nó cũng giúp tôi trả lại kết quả một phần.

Vì vậy, đó là cách tiếp cận của tôi đối với vấn đề:

  1. Tôi nhận được TẤT CẢ các Nhóm Bảo mật EC2 -> all_secgrp
  2. Tôi nhận được TẤT CẢ Phiên bản EC2 -> all_instances
  3. Đối với mỗi Phiên bản, tôi nhận được tất cả các Nhóm bảo mật được đính kèm với nó
    1. Tôi xóa khỏi all_secgrp từng SecurityGroup này (vì được đính kèm)
  4. Đối với mỗi Nhóm bảo mật, tôi kiểm tra liên kết với bất kỳ Giao diện mạng nào (sử dụng filterchức năng và lọc bằng cách sử dụng chức năng đó security-group-id)
    1. NẾU không tìm thấy liên kết nào, tôi xóa nhóm bảo mật khỏi all_secgrp

Bạn có thể thấy một đoạn mã được đính kèm. Đừng phàn nàn về hiệu quả, nhưng hãy cố gắng tối ưu hóa nó nếu bạn muốn.

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

Đây là một vấn đề khó khăn, nếu bạn có các nhóm bảo mật tham chiếu đến các nhóm bảo mật khác trong quy tắc. Nếu vậy, bạn sẽ phải giải quyết DependencyErrors, điều này không hề nhỏ.

Nếu bạn chỉ sử dụng địa chỉ IP, thì giải pháp này sẽ hoạt động, sau khi bạn tạo ứng dụng 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))

Điều này sẽ không bao gồm SGs được sử dụng bởi RDS
alexandernst
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.