Настройка AWS SSO с AWS Client VPN

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

В этом туториале я опишу простую и безопасную настройку мультиаккаунтной инфраструктуры, основанной на AWS, включая SSO и решение для VPN от Amazon.

Введение

Я разбил статью на несколько основных частей:

  • Во-первых, я покажу как создать инфраструктуру в AWS с нуля, с безопасной структурой аккаунтов, сетей, пирингов

  • Вторая часть этой статьи посвящена AWS SSO: пользователям, группам, MFA, и т.д.

  • Третья часть описывает процесс развертывания сервиса AWS VPN с помощью terraform и его настройки для ранее созданных сетей

Начнем!

Структура AWS-аккаунтов

Мультиаккаунтная структура для AWS имеет ряд преимуществ. Я не буду на них останавливаться, только покажу пример:

Структура аккаунтов
Структура аккаунтов

Аккаунт root является главным в организации (на него привязывается биллинг), все остальные аккаунты добавляются под руководство этого аккаунта.

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

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

https://console.aws.amazon.com/organizations/v2/home/accounts
https://console.aws.amazon.com/organizations/v2/home/accounts

Этого достаточно на текущий момент, можем идти дальше.

Сетевая структура

В моем примере аккаунты dev, stage и prod изолированы друг от друга.

Аккаунт common используется для общих сервисов, таких как система CI/CD, хранилища данных (S3-бакеты), и т.д. Поэтому, в моем случае, для того чтобы разрешить сетевое соединение между common и dev/stage/prod аккаунтам, нам нужно создать VPC-пиринг (соединение между виртуальными сетями).

Давайте сделаем это с помощью terraform для аккаунтов common и dev.

Для начала создадим VPC:

data "aws_availability_zones" "available" {}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "3.7.0"

  name = "${var.env}-vpc"
  cidr = var.vpc_cidr
  azs  = data.aws_availability_zones.available.names

  private_subnets = var.vpc_private_subnets
  public_subnets  = var.vpc_public_subnets

  enable_nat_gateway   = true
  single_nat_gateway   = true
  enable_dns_hostnames = true
}

А также файл с входными параметрами terraform.tfvars:

region = "eu-central-1"
env    = "common"

# https://www.davidc.net/sites/default/subnets/subnets.html
# каждая подсеть ~8190 хостов
# 10.0.192.0/19 зарезервирована под VPN-клиентов
vpc_cidr            = "10.0.0.0/16"
vpc_private_subnets = ["10.0.0.0/19", "10.0.32.0/19", "10.0.64.0/19"]
vpc_public_subnets  = ["10.0.96.0/19", "10.0.128.0/19", "10.0.160.0/19"]

Если вы хотите применить то же самое для аккаунта dev, просто скопируйте и вставьте файл и измените значения сетей и подсетей, к примеру на 10.1.0.0/16 и т.д. Помните, что подсети должны быть разными, чтобы избежать их пересечения после пиринга.

После этого мы имеем новые виртуальные сети:

Давайте соединим их с помощью пиринга:

module "common_dev_peering" {
  source  = "grem11n/vpc-peering/aws"
  version = "4.0.1"

  providers = {
    aws.this = aws
    aws.peer = aws.dev
  }

  this_vpc_id = module.vpc.vpc_id
  peer_vpc_id = var.vpc_dev_accepter_id

  auto_accept_peering = true
}

Не забываем указать vpc_dev_accepter_id в файле terraform.tfvars:

...
vpc_dev_accepter_id = "vpc-12345678"

Ту же самую процедуру можно проделать, к примеру, для аккаунтов stage и prod.

Схема соединения частных сетей
Схема соединения частных сетей

Для тестирования сетевого соединения, достаточно в обоих сетях создать виртуалку и попробовать проверить каким-нибудь инструментом типа ping или traceroute.

Настраиваем SSO

Заходим в AWS в аккаунт root, находим сервис AWS SSO и создаем три группы:

Идея состоит в том, чтобы разделять доступ к различным сетям для разных групп (RBAC) с VPN.

Созданные нами группы
Созданные нами группы

Также создадим пользователя, пусть будет amet-umerov, после добавления его во все ранее созданные группы, мы хотим чтобы пользователь получил доступ во все сети с помощью VPN.

Не забываем включать MFA для пользователя
Не забываем включать MFA для пользователя

Итак, мы подготовили группы и пользователя, самое время создать новое SSO-приложение под названием VPN:

Также создадим еще одно SSO-приложение с именем VPN Self-Service с такими же настройками, кроме:

Добавим маппинг атрибутов для этих приложений:

И привяжем к ним все три группы (vpn-devvpn-stagevpn-prod).

Список настроенных приложений
Список настроенных приложений

Вот как оно работает:

Разделение доступа к сетям
Разделение доступа к сетям

Настраиваем VPN

Нашим последним шагом является создание клиентской точки доступа для VPN в аккаунте common. Но перед этим необходимо подготовить некоторые сертификаты и ключи.

Генерируем сертификаты для сервера и клиента:

$ git clone https://github.com/OpenVPN/easy-rsa.git
$ cd easy-rsa/easyrsa3

$ ./easyrsa init-pki
$ ./easyrsa build-ca nopass
...
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:vpn.domain.org

$ ./easyrsa build-server-full vpn-aws-server nopass
$ ./easyrsa build-client-full vpn-aws-client nopass

Копируем сгенерированные сертификаты в безопасное место и импортируем сертификат для сервера в AWS ACM:

$ mkdir ~/.vpn-assets/
$ cp pki/ca.crt ~/.vpn-assets/
$ cp pki/private/ca.key ~/.vpn-assets/
$ cp pki/issued/vpn-aws-*.crt ~/.vpn-assets/
$ cp pki/private/vpn-aws-*.key ~/.vpn-assets/

$ aws --profile common \
    --region eu-central-1 \
    acm import-certificate \
    --certificate fileb://$HOME/.vpn-assets/vpn-aws-server.crt \
    --private-key fileb://$HOME/.vpn-assets/vpn-aws-server.key \
    --certificate-chain fileb://$HOME/.vpn-assets/ca.crt

# На всякий случай скопируем это все в S3-бакет
$ aws --profile=common s3 cp --recursive ~/.vpn-assets/ s3://my-bucket/vpn/

Создаем новое VPN-соединение с помощью terraform:

# SAML провайдеры из метадата-файлов, загруженных нами ранее
resource "aws_iam_saml_provider" "vpn" {
  name                   = "vpn"
  saml_metadata_document = file("${path.module}/files/VPN_ins-mymetadata-file.xml")
}

resource "aws_iam_saml_provider" "vpn_self_service" {
  name                   = "vpn-self-service"
  saml_metadata_document = file("${path.module}/files/VPN Self-Service_ins-mymetadata-file.xml")
}

# Получаем импортированный нами сертификат и subnet_id
data "aws_acm_certificate" "vpn_aws_server_cert" {
  domain   = "vpn-aws-server"
  statuses = ["ISSUED"]
}

data "aws_subnet" "vpn_subnet_id" {
  filter {
    name   = "tag:Name"
    values = ["${var.env}-vpc-private"]
  }
  availability_zone_id = "euc1-az1"
}

# Подготовка CloudWatch для логирования VPN
resource "aws_cloudwatch_log_group" "client_vpn" {
  name = "vpn_endpoint_cloudwatch_log_group"
}

resource "aws_cloudwatch_log_stream" "client_vpn" {
  name           = "vpn_endpoint_cloudwatch_log_stream"
  log_group_name = aws_cloudwatch_log_group.client_vpn.name
}

# Точка доступа VPN
resource "aws_ec2_client_vpn_endpoint" "vpn" {
  description            = "VPN client for AWS"
  server_certificate_arn = data.aws_acm_certificate.vpn_aws_server_cert.arn

  client_cidr_block = var.vpn_client_cidr_block
  dns_servers       = var.vpn_dns_servers

  split_tunnel        = "true"
  self_service_portal = "enabled"
  transport_protocol  = "udp"

  authentication_options {
    type                           = "federated-authentication"
    saml_provider_arn              = aws_iam_saml_provider.vpn.arn
    self_service_saml_provider_arn = aws_iam_saml_provider.vpn_self_service.arn
  }

  connection_log_options {
    enabled               = true
    cloudwatch_log_group  = aws_cloudwatch_log_group.client_vpn.name
    cloudwatch_log_stream = aws_cloudwatch_log_stream.client_vpn.name
  }
}

# Фаерволы для VPN
resource "aws_security_group" "vpn_main" {
  name        = "vpn_main"
  description = "Allow VPN all traffic"
  vpc_id      = module.vpc.vpc_id

  egress {
    description = "Allow all traffic for VPN"
    cidr_blocks = ["0.0.0.0/0"]
    from_port   = "0"
    protocol    = "-1"
    self        = "false"
    to_port     = "0"
  }

  ingress {
    description = "Allow all traffic for VPN"
    cidr_blocks = ["0.0.0.0/0"]
    from_port   = "0"
    protocol    = "-1"
    self        = "false"
    to_port     = "0"
  }
}

# Ассоциируем VPN-точку с подсетью
resource "aws_ec2_client_vpn_network_association" "vpn" {
  client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id
  subnet_id              = data.aws_subnet.vpn_subnet_id.id
  security_groups        = [aws_security_group.vpn_main.id]
}

# Идентификаторы (access_group_id) можно найти тут (в аккаунте root):
# https://eu-central-1.console.aws.amazon.com/singlesignon/home?region=eu-central-1#/groups
resource "aws_ec2_client_vpn_authorization_rule" "vpn_dev" {
  client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id
  target_network_cidr    = "10.10.0.0/16"
  access_group_id        = "1234-5678-..."
  description            = "vpn-dev"
}

# Разрешаем доступ в сеть common для группы vpn-dev
resource "aws_ec2_client_vpn_authorization_rule" "vpn_common" {
  client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id
  target_network_cidr    = "10.0.0.0/16"
  access_group_id        = "1234-5678-..."
  description            = "vpn-common"
}

# Маршруты
resource "aws_ec2_client_vpn_route" "vpn_to_dev" {
  client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id
  destination_cidr_block = "10.10.0.0/16"
  target_vpc_subnet_id   = aws_ec2_client_vpn_network_association.vpn.subnet_id
}

И модифицируем файл terraform.tfvars:

...
vpn_client_cidr_block = "10.0.192.0/19"
vpn_dns_servers       = ["1.1.1.1", "8.8.8.8"]

После применения данной конфигурации мы получаем клиентскую точку доступа к VPN с контролем доступа на уровне ролей (групп).

Тестируем.

Портал самообслуживания
Портал самообслуживания

После всех проделанных ранее манипуляций у нас есть доступ к сетям аккаунтов common и dev с помощью VPN .

Данная конфигурация может быть масштабирована для других аккаунтов с иными правилами доступа и маршрутами в нашем terraform-коде.

Полезные ссылки

Источник: https://habr.com/ru/post/585648/


Интересные статьи

Интересные статьи

Всем доброго времени суток. Начнем. Во время своего обучения этой технологии я столкнулся с проблемой, что на весь интернет есть только один нормальный источник инф...
Предыстория Когда-то у меня возникла необходимость проверять наличие неотправленных сообщений в «1С-Битрикс: Управление сайтом» (далее Битрикс) и получать уведомления об этом. Пробле...
Всем привет! Если вы слышали о Blazor, но до сих пор не понимаете, что это такое. То вы по адресу. Это первая статья из цикла 12 статей, которая проведет вас через все круги ада весь процесс созд...
Этот пост будет из серии, об инструментах безопасности, которые доступны в Битриксе сразу «из коробки». Перечислю их все, скажу какой инструмент в какой редакции Битрикса доступен, кратко и не очень р...
Довольно часто владельцы сайтов просят поставить на свои проекты индикаторы курсов валют и их динамику. Можно воспользоваться готовыми информерами, но они не всегда позволяют должным образом настроить...