乐趣区

关于自动化:基于云服务器-EC2-的云上堡垒机的设计和自动化实现

背景

在很多企业的理论利用场景中,特地是金融类的客户,大部分的利用都是部署在公有子网中,如何可能让客户的开发人员和运维人员从本地的数据中心中平安的拜访云上资源,堡垒机是一个很好的抉择。传统堡垒机的外围实现原理是基于 SSH 协定的平安连贯,通常使用 SSH(Secure Shell)协定实现数据的加密通信。SSH 为平安身份验证和数据加密提供了牢靠保障,从而确保了连贯的安全性。然而,传统的自建堡垒机在其治理和运维方面面临着多种挑战:

1. 部署与保护复杂性 :自建堡垒机的部署和配置往往波及多个简单步骤和组件,导致治理和保护的工作量显著减少。

2. 安全性危险 :自行治理多个密钥和凭证可能会减少安全漏洞的危险。若密钥治理不当,可能导致未经受权的拜访。

3. 可用性问题 :自建堡垒机经常无奈实现高可用性和弹性,多用户同时拜访时可能呈现性能问题,影响用户体验。

4. 扩大艰难 :随着用户数量和需要的减少,自建堡垒机可能难以灵便扩大,导致资源分配不均。

5. 更新和降级 :自建堡垒机须要定期进行更新和降级,以放弃安全性和性能,然而这可能会导致业务中断或不稳固状况。

6. 外网裸露 :传统堡垒机须要在云上环境中部署一个有外网拜访的权限的机器,减少了被攻打的危险。

亚马逊云科技开发者社区为开发者们提供寰球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、流动与比赛等。帮忙中国开发者对接世界最前沿技术,观点,和我的项目,并将中国优良开发者或技术举荐给寰球云社区。如果你还没有关注 / 珍藏,看到这里请肯定不要匆匆划过,点这里让它成为你的技术宝库!

与传统形式不同,基于 Amazon Systems Manager Session Manager 的堡垒机通过建设双向加密通道,连贯客户端和近程节点,并采纳 TLS 1.2 进行流量加密和 Sigv4 签名申请。这一形式具备显著劣势:

1. 一键式部署 :该计划极大简化了堡垒机部署流程,从而缩小了部署难度和运维老本。

2. 卓越安全性 :Session Manager 提供了加密和身份验证性能,保障连贯的安全性。

  • 基于 Amazon Web Services Identity and Access Management (IAM) 角色的最小权限准则,管理员可能通过集中的 IAM 策略管理堡垒机的拜访受权。
  • 无需治理堡垒机密钥。
  • 反对云上公有子网部署,无需部署在私有子网中,且无需关上入站端口。

3. 高可用性 :通过弹性伸缩性能实现了堡垒机的跨可用区高可用性。

4. 可扩展性 :基于 CPU 利用率的弹性伸缩策略可能主动调整容量,以适应不同流量拜访的需要。

5. 简化治理 :Systems Manager Session Manager 是一项无需用户自行治理实例的托管服务。无需事后启动实例,也无需将实例间接裸露在公网上,从而升高了治理复杂性。

6. 端口转发与跨平台反对 :通过 Session Manager,可在本地客户端进行近程节点端口转发,并实现连贯。同时,它对 Linux、Windows、Mac 等多种操作系统平台提供了跨平台拜访反对。

7. 全面的日志记录与审计 :Session Manager 反对多种形式进行日志记录,涵盖登录工夫、命令执行等内容,以确保会话连贯流动失去残缺记录。这些记录可用于审计和故障排除。

8. 提供监控告警性能 :针对堡垒机的性能指标进行监控告警,以便在性能异样时及时收到告诉。

基于 Session Manager 的堡垒机为拜访治理提供了高效、平安、高可用的解决方案,成为晋升操作效率和保障安全性的现实抉择。堡垒机作为一种安全措施,容许用户通过两头主机来拜访位于公有子网中的实例或资源。它作为一座桥梁,帮忙用户在平安的环境下连贯到外部资源,同时缩小对间接连贯的需要,从而升高被攻打的危险。对于企业的平安管理员来说,堡垒机能够加强安全性、简化网络配置、升高网络资源裸露危险、提供审计跟踪,对于开发运维人员来说,他们能够在本地环境中应用相熟的开发、运维工具,如数据库客户端、浏览器、RDP 等去拜访云上公有资源,大大提高生产效率。

本文次要论述的是基于 Amazon Systems Manager 的 Session Manager 个性和 Amazon EC2 堡垒机的设计和实现。次要内容包含堡垒机的架构设计、平安设计、日志监控设计、高可用弹性设计以及自动化部署设计等,同时针对堡垒机在不同场景中的应用形式和脚本进行举例说明。

云上堡垒机设计

2.1 平安设计

在进行云上堡垒机设计时,平安是第一个须要思考的要求。Session Manager 是一种无需通过公网 IP 或 SSH 密钥来连贯到 EC2 实例的服务,它通过 Systems Manager 的控制台或 CLI 来创立和治理平安的交互式会话。其平安设计次要思考以下四点:

  • IAM 权限和访问控制

    • Session Manager 权限:确保只有受权的用户或角色领有应用 Session Manager 的权限。为用户或角色调配适当的 IAM 策略,限度其对 Session Manager 的拜访,个别状况下,通过与客户已有的 AD 进行集成,通过分组来管制启动 Session Manager 的权限。
    • 多因素认证(MFA):强制启用多因素认证,减少用户身份验证的安全性。
  • VPC 和子网安全性

    • 管制对 Session Manager 的网络拜访:设置 VPC Endpoints 的平安组仅容许来自堡垒机及公有子网中主机的拜访,并且设置 VPC Endpoints 的策略,以限度特定受信赖实体能力拜访。
  • 日志和审计

    • 监控 Session Manager 会话:启用 CloudTrail 以记录 Session Manager 的 API 调用流动,以便审计和监控用户对会话的操作;配置 Session Manager 参数,发送会话日志到 Amazon CloudWatch 日志组和 S3 存储桶,确保用户在会话中的所有操作均被记录,CloudWatch 日志组中的数据将保留 3 个月,S3 桶中的会话日志将长久存储以满足安全监管和审计需要。同时,通过脚本来实现对本地 Session Manager 插件 SSH 登录上的操作进行具体记录,并存储在指定的存储桶中。
  • 平安加密

    • 加密各类堡垒机相干资源:应用 Amazon Key Management Service(KMS)对 Session Manager 的会话进行加密,加密 Amazon CloudWatch 日志组及 S3 存储桶,以确保会话和日志的安全性。

2.2 高可用和弹性设计

堡垒机的高可用设计能够确保在产生故障或负载减少时,堡垒机依然可能放弃可用,并持续提供平安的访问控制。

  • 堡垒机的高可用性

    • 应用 Auto Scaling Group(ASG):配置堡垒机所在的 EC2 实例为一个 Auto Scaling Group。当堡垒机实例的负载减少时,ASG 会依据设置的扩大规定主动减少实例数量,放弃高可用性。
    • 设置负载平衡:当多个堡垒机实例同时运行时,能够应用负载均衡器来散发流量,确保各个实例的负载平衡。负载均衡器还能够在某些实例呈现故障时主动将流量路由到其余衰弱的实例,进步了整体的可用性。
  • 定时扩大和缩减

    • 通过 Auto Scaling Group 的定时规定,管制堡垒机的启动和关机工夫,从而来节约堡垒机的费用。

2.3 监控告警设计

  • Amazon CloudWatch 指标监控:CloudWatch 能够监控 EC2 实例和其余亚马逊云资源的性能指标。可监控实例的 CPU 使用率、内存利用率、磁盘等要害指标。并通过 Amazon SNS 服务设置报警,以便在性能异样时及时收到告诉。

2.4 自动化部署设计

2.4.1 堡垒机代码设计

思考到堡垒机的高可用设计,在其中一台机器宕机的状况下,能够主动、疾速的拉起一台新的堡垒机以供应用,咱们采取 EC2 launch template 的形式进行堡垒机的构建,以下是 IaC 样例代码:

1. 通过弹性伸缩启动模版创立堡垒机的 IaC 代码样例,蕴含启动模版、弹性伸缩组、弹性规定等。

## 创立 Bastion 的 launch template
resource "aws_launch_template" "bastion_template" {
  name = "bastion_template"
  block_device_mappings {
    device_name = "/dev/xvda"
    ebs {
      volume_size = 8
      encrypted   = true
    }
  }

  iam_instance_profile {name = aws_iam_instance_profile.bastion_ec2_profile.id}

  image_id                             = data.aws_ami.linux_2023_image.id
  instance_initiated_shutdown_behavior = "terminate"
  instance_type                        = var.bastion_instance_type
  
  monitoring {enabled = true}

  network_interfaces {
    associate_public_ip_address = false
    device_index                = 0
    security_groups             = [aws_security_group.bastion.id]
    subnet_id                   = element(module.vpc.private_subnets, 0)
    delete_on_termination       = true
  }

  user_data = base64encode(
    templatefile("${path.module}/templates/user_data.sh.tftpl",
      {## 传入值到 user data 中所须要的变量中}
    )
  )
}

## 创立 Bastion 的弹性伸缩组
resource "aws_autoscaling_group" "bastion_asg" {
  launch_template {
    id      = aws_launch_template.bastion_template.id
    version = "$Latest"
  }
  availability_zones        = ["${var.region}a","${var.region}b"]
  name                      = "bastion_daily"
  max_size                  = 1
  min_size                  = 1
  health_check_grace_period = 300
  health_check_type         = "EC2"
  force_delete              = true
  termination_policies      = ["OldestInstance"]

  tag {
    key                 = "Name"
    value               = "bastion"
    propagate_at_launch = true
  }
}

## 创立 Bastion 的弹性伸缩规定 - 样例中应用定时规定
resource "aws_autoscaling_schedule" "bastion_scale_down" {
  scheduled_action_name  = "bastion_scale_down"
  min_size               = 0
  max_size               = 0
  desired_capacity       = 0
  recurrence             = "0 20 * * *" # 20:00 UTC +8 工夫
  time_zone              = "Asia/Chongqing"
  autoscaling_group_name = aws_autoscaling_group.bastion_asg.name
}

resource "aws_autoscaling_schedule" "bastion_scale_up" {
  scheduled_action_name  = "bastion_scale_up"
  min_size               = 1
  max_size               = 1
  desired_capacity       = 1
  recurrence             = "0 8 * * *" # 8:00 UTC +8 工夫
  time_zone              = "Asia/Chongqing"
  autoscaling_group_name = aws_autoscaling_group.bastion_asg.name
}

## 或者基于 CPU 利用率的弹性伸缩规定(样例)resource "aws_autoscaling_group" "bation_cpu" {
  name                 = "bastion-cpu-asg"
  launch_configuration = aws_launch_configuration.bastion_template.name
  min_size             = 2
  max_size             = 4
  desired_capacity     = 2
  
  metric_trigger {
    metric_name = "CPUUtilization"
    namespace   = "AWS/EC2"
    statistic   = "Average"
    unit        = "Percent"
    threshold   = 70  # CPU 利用率超过 70% 时扩容
    comparison_operator = "GreaterThanOrEqualToThreshold"

    dimensions = {AutoScalingGroupName = aws_autoscaling_group.bastion_cpu.name}
  }

  scaling_policy {
    name = "scale-up-policy"
    adjustment_type         = "ChangeInCapacity"
    scaling_adjustment      = 1
    cooldown               = 300  # 冷却工夫 300s
  }

2. 定义堡垒机的 EC2 用户数据代码样例

在创立堡垒机时,不仅仅是独自的创立一台 EC2 的实例,还须要针对用于该 EC2 的实例进行平安加固、装置相应的工具、设置对于堡垒机的监控等性能,以下是 IaC 代码中,用于 EC2 实例初始化的用户数据(User Data)样例。

## 平安加固
yum -y update --security

## 仅容许 ec2-user 拜访该目录
mkdir /var/log/bastion
chown ec2-user:ec2-user /var/log/bastion
chmod -R 770 /var/log/bastion
setfacl -Rdm other:0 /var/log/bastion

## Make OpenSSH execute a custom script on logins
echo -e "\\nForceCommand /usr/bin/bastion/shell" >> /etc/ssh/sshd_config
echo "AllowTcpForwarding yes" >> /etc/ssh/sshd_config
awk '!/X11Forwarding/' /etc/ssh/sshd_config > temp && mv temp /etc/ssh/sshd_config
echo "X11Forwarding no" >> /etc/ssh/sshd_config

sed  -i "s/002/022/g" /etc/profile
umask 022

## SSH 命令记录脚本
mkdir /usr/bin/bastion
cat > /usr/bin/bastion/shell << 'EOF'

  # The format of log files is /var/log/bastion/YYYY-MM-DD_HH-MM-SS_user
  LOG_FILE="`date --date="today""+%Y-%m-%d_%H-%M-%S"`_`whoami`"LOG_DIR="/var/log/bastion/"echo""
  echo "NOTE: This SSH session will be recorded"
  echo "AUDIT KEY: $LOG_FILE"
  echo ""
  SUFFIX=`mktemp -u _XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`
  script -qf --timing=$LOG_DIR$LOG_FILE$SUFFIX.time $LOG_DIR$LOG_FILE$SUFFIX.data --command=/bin/bash
EOF

chmod a+x /usr/bin/bastion/shell
chown root:ec2-user /usr/bin/script
chmod g+s /usr/bin/script

## 敞开根用户登录
systemctl stop sshd
echo "PermitRootLogin no" >> /etc/ssh/sshd_config
echo "PermitEmptyPasswords no" >> /etc/ssh/sshd_config
systemctl start sshd

## 装置 CloudWatch Agent,进行系统日志收集及性能指标收集
sudo yum -y install amazon-cloudwatch-agent
sudo yum install -y collectd
cat > /opt/aws/amazon-cloudwatch-agent/etc/config.json << _EOF_
{
    "agent": {
            "metrics_collection_interval": 60,
            "run_as_user": "root"
    },
    "logs": {
            "logs_collected": {
                    "files": {
                            "collect_list": [
                                    {
                                            "file_path": "/var/log/messages",
                                            "log_group_name": "/aws/ec2/bastion/messages",
                                            "log_stream_name": "{instance_id}",
                                            "retention_in_days": 30
                                    },
                                    {
                                            "file_path": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log",
                                            "log_group_name": "/aws/ec2/bastion/amazon-cloudwatch-agent",
                                            "log_stream_name": "{instance_id}",
                                            "retention_in_days": 30
                                    }
                            ]
                    }
            }
    },
    "metrics": {
            "aggregation_dimensions": [
                    ["InstanceId"]
            ],
            "append_dimensions": {"AutoScalingGroupName": "$${aws:AutoScalingGroupName}",
                    "InstanceId": "$${aws:InstanceId}"
            },
            "metrics_collected": {
                    "collectd": {"metrics_aggregation_interval": 60},
                    "disk": {
                            "measurement": [
                                {
                                    "name":"used_percent",
                                    "rename":"disk_used_percent"
                                }
                            ],
                            "metrics_collection_interval": 60,
                            "resources": ["*"]
                    },
                    "mem": {
                            "measurement": [
                                {
                                    "name":"used_percent",
                                    "rename":"mem_used_percent"
                                }    
                            ],
                            "metrics_collection_interval": 60
                    },
                    "statsd": {
                            "metrics_aggregation_interval": 60,
                            "metrics_collection_interval": 10,
                            "service_address": ":8125"
                    }
            }
    }
}
_EOF_

sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/config.json -s
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a start

3. 设计和创立堡垒机平安组

依据 Session Manager 平安组的最佳实际,本计划中堡垒机的平安组设计如下:

入站规定

协定 端口 备注
NA NA NA 无入站规定

出站规定

指标 协定 端口 备注
VPC CIDR TCP 0-65535 容许拜访 VPC 外部资源
VPC endpoints Security group ID HTTPS 443 容许拜访 VPC Interface endpoints
VPC endpoints S3 prefix list HTTPS 443 容许拜访 S3 Gateway endpoint

IaC 代码设计样例如下:

# 创立堡垒机平安组并配置规定
resource "aws_security_group" "bastion" {
  description = "Ingress should be only from Systems Session Manager"
  name        = "bastion-sg"
  vpc_id      = module.vpc.vpc_id

  tags = merge(
    {Name = "bastion-sg"}
  )
}

resource "aws_security_group_rule" "basion_egress_1" {
  security_group_id = aws_security_group.bastion.id

  description = "bastion_to_local_VPC_CIDRs"
  type        = "egress"
  from_port   = "0"
  to_port     = "65535"
  protocol    = "TCP"
  cidr_blocks = [local.vpc_cidr]
}

resource "aws_security_group_rule" "basion_egress_2" {
  security_group_id = aws_security_group.bastion.id

  description              = "bastion_egress_to_inteface_endpoints"
  type                     = "egress"
  from_port                = "443"
  to_port                  = "443"
  protocol                 = "TCP"
  source_security_group_id = aws_security_group.vpc_endpoints.id
}

resource "aws_security_group_rule" "bastion_linux_3" {
  security_group_id = aws_security_group.bastion.id

  description     = "bastion_linux_egress_to_s3_endpoint"
  type            = "egress"
  from_port       = "443"
  to_port         = "443"
  protocol        = "TCP"
  prefix_list_ids = [data.aws_vpc_endpoint.s3.prefix_list_id]
}

2.4.2 Session Manager 配置设计

在启用 Session Manager 时,须要对 Session Manager 进行相干的配置,如是否开启 Session 加密,是否将日志存储到 CloudWatch Logs 或者 S3 上,是否对日志进行加密,最大的 Session 时长等。咱们通过创立 SSM Documents 的形式来进行配置,如以下 IaC 样例代码所示:

## ssm run shell json
{
    "schemaVersion": "1.0",
    "description" : "Document for SSM log configuration",
    "sessionType" : "Standard_Stream",
    "inputs": {"s3BucketName" : "${bucket_name}",
        "s3KeyPrefix" : "ssm",
        "s3EncryptionEnabled" : true,
        "cloudWatchLogGroupName" : "${log_group_name}",
        "cloudWatchEncryptionEnabled" : true,
        "cloudWatchStreamingEnabled": true,
        "kmsKeyId" : "${kms_id}",
        "runAsEnabled": true,
        "idleSessionTimeout": "20",
        "maxSessionDuration":"60",
    } 
}

## IaC code 创立 SessionManagerRunShell documents
resource "aws_ssm_document" "ssm_shell" {
  name            = "SSM-SessionManagerRunShell"
  document_format = "JSON"
  document_type   = "Session"
  content = templatefile("${path.module}/templates/ssm_runshell.json", {bucket_name    = join("-", [local.bucket_name, data.aws_caller_identity.current.account_id])
    log_group_name = "/aws/sessionmanager"
    kms_id         = aws_kms_key.this.arn
    }
  )
}

2.4.3 堡垒机 IAM 角色设计

在本设计中,堡垒机的 IAM 角色次要蕴含以下权限:

  • AmazonSSMManagedInstanceCore
  • CloudWatchAgentServerPolicy
  • Logs 局部权限
  • SSM Messages 局部权限
  • S3 局部权限
  • KMS 局部权限

如需自定义更多 Session Manager IAM 角色的具体可拜访:自定义 Session Manager IAM 角色

以下是 IaC 代码样例:

## 关联托管的 IAM Policy
resource "aws_iam_role_policy_attachment" "bastion_managed" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
  role       = aws_iam_role.bastion_role.name
}

resource "aws_iam_role_policy_attachment" "bastion_managed_cloudwatch" {
  policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
  role       = aws_iam_role.bastion_role.name
}

## 创立 IAM 角色及关联的 Policy Documents
data "aws_iam_policy_document" "bastion_assume_policy_document" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "bastion_role" {
  name               = "bastion_ec2_role"
  path               = "/"
  assume_role_policy = data.aws_iam_policy_document.bastion_assume_policy_document.json

  tags = merge(
    {Name = "bastion_linux_ec2_role"},
  )
}

部署堡垒机

本章将介绍如何通过基础设施即代码(Infrastructure as code)的形式一键式构建云上堡垒机,通过 Terraform 进行相应的 IaC 代码开发。

3.1 堡垒机部署架构图

依据云上堡垒机的设计,咱们在堡垒机的部署中,将应用到亚马逊云上的多种服务:如 Amazon CloudWatch、Key Management Service(KMS)、Identity and Access Management(IAM)、Systems Manager、Amazon Simply Notification Service(SNS)、Amazon Simple Storage Service(S3)、Amazon PrivateLink、Amazon EC2 以及 Amazon EC2 Auto Scaling 等,以下为部署架构图:

图 3-1 堡垒机部署架构图

以下对部署中所应用到的次要亚马逊云相干服务的用处进行简略介绍:

  • Amazon EC2/Amazon EC2 Auto Scaling:在 EC2 上进行堡垒机的部署,并通过 AutoScaling 确保堡垒机的高可用;
  • Amazon Simple Storage Service(S3):用于寄存通过 Session Manager 和 SSH 登录到堡垒机上所产生的操作日志信息;
  • Amazon VPC endpoints:用于堡垒机在没有外网拜访的条件下,进行平安的拜访如 Amazon CloudWatch(Logs/Monitoring)、Amazon S3、Systems Manager、Amazon KMS 等服务;
  • Amazon CloudWatch:用于寄存通过控制台的 Session Manager 性能拜访堡垒机的操作日志存储;
  • Amazon KMS:用于加密堡垒机部署过程中的相干服务,如 Session 加密、CloudWatch logs 加密、S3 桶加密等;
  • Amazon Simply Notification Service:用于承受 Bastion Host 在 CPU/Memory/ 磁盘超过阈值的时候的告警信息。

须要创立的 Endpoints 列表:

3.2 堡垒机自动化部署

当 IaC 代码开发实现后,能够将该代码集成在其余资源的 CICD pipeline 中,也能够通过 Terraform 命令,间接进行部署。

# Terraform plan 查看要部署的 Bastion 资源
$ terraform plan -var-file=common.tfvars  ## common.tfvars 蕴含堡垒机所需的相干参数

# Terraform apply 执行部署
$ terraform apply -var-file=common.tfvars

等到命令执行实现后,登录到亚马逊云科技治理控制台查看相应资源是否依照预期部署实现。

堡垒机应用场景

4.1 堡垒机应用前置条件

如果要在本地机器上应用堡垒机,须要满足以下条件:

  1. 确保亚马逊云上堡垒机曾经部署实现,并且处于 running 状态;
  1. 确保网络联通性,确认堡垒机能拜访私网环境中的 RDS 数据库、WebServer EC2 等;
  1. 确保你本地应用的 IAM 角色至多具备以下权限:

    • ec2:DescribeInstances
    • ssm:StartSession
    • ec2-instance-connect:SendSSHPublicKey
  1. 确保本地环境中正确装置了亚马逊云命令行工具(CLI V2)和 Session Manager 插件

4.2  堡垒机应用场景实操

假如客户在亚马逊云上的公有子网中,部署了一个 Web 利用,蕴含 Web 前端和服务后端以及 RDS 数据库(以 SQL Server 为例)。该客户对于安全性的要求十分高,云上 VPC 环境中没有 Internet 拜访,也没有在本地网络与云上环境之间搭建专线直连(Direct Connect)和 VPN。但客户的开发人员和运维人员,要求提供一个平安、高效、牢靠的形式从本地的客户端、应用程序、浏览器去拜访云上资源,以进步开发、运维效率。下图为堡垒机实操环境的部署示意图:

 图 4-1 堡垒机实操环境部署示意图

4.2.1  场景一:通过亚马逊云科技治理控制台 / 命令行登录堡垒机

在这个场景中,开发人员或者运维人员通过公司 AD 集成的账号拿到了相应的角色权限,间接登录到亚马逊云的治理控制台,而后通过 Session Manager 间接连贯到堡垒机上进行操作。操作步骤如下:

  • 形式一:间接进入到 EC2 控制台,抉择堡垒机,而后点击“Connect”进行连贯
  • 形式二:进入到 Systems Manager→ Session Manager→ Start Session,而后抉择堡垒机进行连贯

两种形式登录后,进入的界面如下图所示:

 图 4-2 通过控制台登录堡垒机

或者在本地启动 SSM Session Manager 的插件,从本地电脑中,间接拜访堡垒机:

## 通过 CLI 获取 Bastion 的 Instance ID
$ InstanceID=$(aws ec2 describe-instances --no-cli-pager \
    --filters "Name=tag:Name,Values=bastion_linux" \
    --query 'Reservations[0].Instances[0].InstanceId' --output text) 

## 启动本地会话
$ aws ssm start-session --target $InstanceID

图 4-3 通过 CLI 从本地机器登录堡垒机

通过控制台或者本地 CLI 进入到堡垒机后,所有的操作都会被记录到 Amazon CloudWatch Log Group “/aws/sessionmanager”,日志保留工夫为 3 个月, 并且还会上传到 S3 桶(S3 桶名:bastion-audit-log-bucket-<AccountID>,门路为:ssm/)中做长久化存储。

 图 4-4 日志组中存储的堡垒机操作审计日志

 图 4-5 S3 中存储的堡垒机操作审计日志

4.2.2 场景二:通过堡垒机实现近程主机端口转发

在该场景中,开发人员或者运维人员通过公司 AD 集成的账号拿到了相应的角色权限,而后在本地启动 Session Manager 插件 来进行近程主机的端口转发,通过这种形式,开发人员或运维人员能够不便的应用本地客户端进行操作云上资源,如拜访云上数据库和拜访 WebServer 等。以下命令是启动如何在本地机器上实现近程主机端口转发:

## 通过 CLI 获取 Bastion 的 Instance ID
$ InstanceID=$(aws ec2 describe-instances --no-cli-pager \
    --filters "Name=tag:Name,Values=bastion_linux" \
    --query 'Reservations[0].Instances[0].InstanceId' --output text) 

## 启动近程主机端口转发,请替换掉命令中的 <> 为理论的近程端口、本地端口以及近程主机 IP 或者 DNS
$ aws ssm start-session --target $InstanceID \
      --document-name AWS-StartPortForwardingSessionToRemoteHost \
      --parameters '{"portNumber":["<Remote_Host_Port_Number>"],"localPortNumber":["<LocalPortNumber>"],"host":["<Remote_Host_DNS/IP>"]}'

(1) 远端数据库端口转发

以在本地拜访云上 SQLServer 数据库为例子,端口号为 1433,本地端口号为  12345,近程主机 DNS 为:“bastion-test-db.xxxxx.<REGION>.rds.amazonaws.com”,启动后,如下图所示:

 图 4-6 本地启动近程主机端口转发(DNS)

关上本地 SQLServer 客户端,输出 RDS Server 端地址和端口:“127.0.0.1,12345”,并输出登录数据库的账号和明码,如下图所示:

图 4-7 配置本地数据库客户端连贯

点击“Connect”,即可拜访云上 RDS 数据库并进行操作:

 图 4-8 本地数据库客户端连贯 RDS 胜利

(2) 远端服务器端口转发

以本地通过浏览器拜访 Web Server 为例,端口号为 80,本地端口号为 8080,近程主机 IP 为:“10.99.3.132”,启动后,如下图所示:

 图 4-9 本地启动近程端口转发(IP 地址)

通过本地浏览器拜访 127.0.0.1:8080,可看到可能胜利拜访到位于公有网络中的 WebServer:

 图 4-10 本地浏览器胜利拜访 WebServer

4.2.3  场景三:通过本地 SSH 连贯到堡垒机

在开发人员或者运维人员在理论工作中,偶然会须要通过 SSH 连贯到堡垒机或者远端的主机上进行调试或者运维,并上传相应的文件到堡垒机上。个别状况下,运维人员须要拿到 EC2 的密钥并确保安全组中蕴含有 22 端口及客户端的 IP 地址的入站规定,而后能力连贯到云上服务器上,这种状况不仅减少了密钥治理的难度,同时对于只存在公有网络中的服务器且本地数据中心和云上环境没有互联的场景是一个很大的挑战。通过 ec2-instance-connect 服务个性并联合 Session Manager 能够不便的满足客户通过 SSH 拜访云上 EC2 的情景。

## Step 1: 通过 CLI 获取 Bastion 的 Instance ID
$ InstanceID=$(aws ec2 describe-instances --no-cli-pager \
    --filters "Name=tag:Name,Values=bastion_linux" \
    --query 'Reservations[0].Instances[0].InstanceId' --output text)
 
## Step 2: 生成长期 ssh key
$ echo -ne "Generating SSH key pair................\r"
$ echo -e 'y\n' | ssh-keygen -t rsa -f temp-key -N '' > /dev/null 2>&1

## Step 3: 发送生成 SSH public key 到堡垒机中,依据理论状况替换掉命令行中的变量
$ echo -ne "Pushing public key to instance.........\r"
$ aws ec2-instance-connect send-ssh-public-key --region $AWS_DEFAULT_REGION \
    --instance-id $instanceId --availability-zone <az> \
    --instance-os-user <ssm_user> \
    --ssh-public-key file://temp-key.pub > /dev/null 2>&1

## Step 4: 批改 ~/.ssh/config 配置(仅须要一次配置)Host test-ssh-bastion
     IdentityFile ~/test/temp-key
     StrictHostKeyChecking no
     UserKnownHostsFile /dev/null
     LogLevel QUIET
     User ec2-user
     ProxyCommand sh -c "aws ssm start-session --target $(aws ec2 describe-instances --no-cli-pager \
        --filters 'Name=tag:Name,Values=bastion_linux' \
        --query 'Reservations[0].Instances[0].InstanceId' --output text) \
     --document-name AWS-StartSSHSession --parameters 'portNumber=%p' --region us-east-1"

## Step 5: 批改实现后,通过 ssh 就能够连贯到堡垒机中, 如下图所示
$ ssh test-ssh-bastion

将以上代码中的 Step1 到 Step3 编写成一个脚本,在每次执行 ssh 之前,先运行该脚本,确保新生成的 SSH Key 无效(通过 send-ssh-public-key 上传到 EC2 上的 Key 有效期只有 60s)。

图 4-11 启动本地 SSH 拜访堡垒机

留神:如果应用动静生成 SSH Key 的形式,须要先创立“EC2 Instance Connect Endpoint”,同时确保本地电脑上应用的 IAM 角色蕴含有“ec2-instance-connect:SendSSHPublicKey”的权限。另外,亚马逊云科技中国区临时不反对该 Endpoint 类型的创立。

通过本地 Session Manager 插件 SSH 进入到堡垒机后,所有的操作都会上传到 S3 桶(S3 桶名:bastion-audit-log-bucket-<AccountID>,门路为:logs/)中做长久化存储。

图 4-12 S3 中存储的在本地通过 SSH 操作堡垒机的审计日志

除通过 SSH 登录到堡垒机外,SSM 还能够反对 SSH Socks Proxy,如下图在浏览器中设置 Proxy(以 Firefox 为例):

 图 4-13 Socks Proxy 配置

应用以下代码启动 SSH Socks Proxy:

ssh -f -N -p 2200 -i temp -o "IdentitiesOnly=yes" -D 1080 ec2-user@localhost

启动后,就能够通过 Socks Proxy 拜访内网的 WebServer。

将来架构演进

本计划中堡垒机是依据最罕用的性能,如端口转发、SSH 拜访来设计的,但在一些特定的场景中,还须要设计更多简单的堡垒机计划,如:Windows 类型的堡垒机反对、如何应用 IAM 角色对堡垒机权限进行更精细化的治理等,这些都是将来本计划演进和加强的一个方向。目前咱们计划中,创立的堡垒机类型只有一种,任何领有启动 Session Manager 的 IAM 用户 / 角色都能够去拜访它并进行操作,但在一些场景下,客户须要对于不同的角色应用不同的堡垒机:如角色 A 仅能够拜访堡垒机 A,并通过该堡垒机上赋予的 IAM 权限进行相应的操作;角色 B 仅能够拜访堡垒机 B,通过该堡垒机上赋予的 IAM 权限进行相应的操作。不同的用户角色和客户自有的 AD 域控进行集成,能够灵便的进行更精细化的权限管制。

总结

本文次要介绍了基于 Amazon Systems Manager Session Manager 的堡垒机的设计和实现,并通过 IaC 自动化形式构建和部署云上堡垒机,同时基于堡垒机的应用场景进行了举例,介绍了不同场景下堡垒机的应用办法和步骤。该堡垒机计划曾经集成到 Cloud Foundations 疾速启动包服务中,为企业用户提供更便捷的部署形式。

参考文档

  • Amazon Systems Manager Session Manager 官网文档
  • Amazon 官网博客:New – Port Forwarding Using AWS System Manager Session Manager

文章起源:https://dev.amazoncloud.cn/column/article/650a818e21a60a3e627…

退出移动版