繁体   English   中英

Cloudformation 堆栈默认参数 SSM 参数存储

[英]Cloudformation stack default parameter SSM Parameter store

我正在尝试使用 cloudformation 启动一个 jupyterlab 实例(这是我经常做的事情,sagemaker 没有 1y 免费层)所以一开始看起来像这样不起作用。 特别是密码参数

# AWSTemplateFormatVersion: "2010-09-09"
Description: Creates a Jupyter Lab Instance with an Elastic Load Balancer


Parameters:
  KeyName:
    Description: >-
      Name of an existing EC2 KeyPair to enable SSH access to the instance
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: Must be the name of an existing EC2 KeyPair.
    Default: eduinstance
  VPC:
    Description: VPC ID of the VPC in which to deploy this stack.
    Type: AWS::EC2::VPC::Id
    ConstraintDescription: Must be the name of a valid VPC
    Default: vpc-10a7ac6a
  Subnets:
    Type: List<AWS::EC2::Subnet::Id>
    Default: subnet-8cde25d3,subnet-531fda72,subnet-4bbe3006
    Description: >-
      Subnets for the Elastic Load Balancer.
      Please include at least two subnets
  Password: 
    Type: String
    NoEcho: false
    MinLength: 4
    Default: '{{resolve:ssm:JLabPassword:1}}'
    Description: Password to set for Jupyter Lab
  EBSVolumeSize:
    Type: Number
    Description: EBS Volume Size (in GiB) for the instance
    Default: 8
    MinValue: 8
    MaxValue: 64000
    ConstraintDescription: Please enter a value between 8 GB and 64 TB
  EC2InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues:
      - t2.micro
      - c5.large
      - m5.large
    Description: Enter t2.micro, c5.large or m5.large. Default is t2.micro.


Conditions:
  JupyterPasswordDefault: !Equals
    - !Ref Password
    - DEFAULT

Resources:
  ALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties: 
      IpAddressType: ipv4
      Scheme: internet-facing
      SecurityGroups: 
        - !GetAtt [ALBSG, GroupId]
      Subnets: !Ref Subnets
      Type: application
  
  ALBListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions: 
        - Type: forward
          TargetGroupArn: !Ref ALBTargetGroup
      LoadBalancerArn: !Ref ALB
      Port: 80
      Protocol: HTTP
  
  ALBTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Port: 8888
      Protocol: HTTP
      Targets: 
        - Id: !Ref ComputeInstance
      TargetType: instance
      VpcId: !Ref VPC
  
  ComputeInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref ComputeIAMRole

  
  ComputeInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      SubnetId: !Select [0, !Ref Subnets]
      KeyName: !Ref KeyName
      ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2:33}}'
      SecurityGroupIds: 
        - !GetAtt [ComputeSG, GroupId]
      IamInstanceProfile: !Ref ComputeInstanceProfile
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeType: gp2
            VolumeSize: !Ref EBSVolumeSize
            DeleteOnTermination: true
      UserData:
        Fn::Base64: !Sub
          - |
            #!/bin/bash
            yum update -y
            yum install python3-pip -y
            yum install java-1.8.0-openjdk -y
            cd /home/ec2-user/
            wget https://repo.anaconda.com/archive/Anaconda3-2020.11-Linux-x86_64.sh
            sudo -u ec2-user bash Anaconda3-2020.11-Linux-x86_64.sh -b -p /home/ec2-user/anaconda
            echo "PATH=/home/ec2-user/anaconda/bin:$PATH" >> /etc/environment
            source /etc/environment
            jupyter notebook --generate-config
            mkdir .jupyter
            cp /root/.jupyter/jupyter_notebook_config.py /home/ec2-user/.jupyter/
            echo "c = get_config()" >> .jupyter/jupyter_notebook_config.py
            echo "c.NotebookApp.ip = '*'" >> .jupyter/jupyter_notebook_config.py
            NB_PASSWORD=$(python3 -c "from notebook.auth import passwd; print(passwd('${password}'))")
            echo "c.NotebookApp.password = u'$NB_PASSWORD'" >> .jupyter/jupyter_notebook_config.py
            rm Anaconda3-2020.11-Linux-x86_64.sh
            mkdir Notebooks
            chmod 777 -R Notebooks .jupyter
            su -c "jupyter lab" -s /bin/sh ec2-user
          - password: !Ref Password #!If [JupyterPasswordDefault, '{{resolve:ssm:JupyterLabPassword:1}}', !Ref Password]

  
  ALBSG:
    Type: AWS::EC2::SecurityGroup
    Properties: 
      GroupDescription: Security Group for JupyterLab ALB. Created Automatically.
      SecurityGroupIngress: 
        - CidrIp: 0.0.0.0/0
          Description: Allows HTTP Traffic from anywhere
          FromPort: 80
          ToPort: 80
          IpProtocol: tcp

  ComputeSG:
    Type: AWS::EC2::SecurityGroup
    Properties: 
      GroupDescription: Security Group for JupyterLab EC2 Instance. Created Automatically.
      SecurityGroupIngress: 
        - Description: Allows JupyterLab Server Traffic from ALB.
          FromPort: 8888
          IpProtocol: tcp
          SourceSecurityGroupId: !GetAtt [ALBSG, GroupId]
          ToPort: 8890
        - CidrIp: 0.0.0.0/0
          Description: Allows SSH Access from Anywhere
          FromPort: 22
          ToPort: 22
          IpProtocol: tcp
  
  ComputeIAMRole:
    Type: AWS::IAM::Role
    Properties: 
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Description: Allows EC2 Access to S3. Created Automatically.
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
        - arn:aws:iam::aws:policy/AmazonSageMakerFullAccess

Outputs:
  URL:
    Description: URL of the ALB
    Value: !Join 
      - ''
      - - 'http://'
        - !GetAtt 
          - ALB
          - DNSName
  
  ConnectionString:
    Description: Connection String For SSH On EC2
    Value: !Join
      - ''
      - - 'ssh -i "'
        - !Ref KeyName
        - '.pem" ec2-user@'
        - !GetAtt
          - ComputeInstance
          - PublicDnsName

然而,它从字面上解释字符串,所以我实际上并没有得到我的密码,而是解析......本身。

实际参数截图

基于 OP 的评论和新的更新模板,并扩展 @DennisTraub 答案。

SSM 参数在模板中的几乎所有情况下都解析,除了UserData (顺便说一句, Init也不起作用)。 这意味着,在UserData的上下文中使用时,动态引用将无法解析 这是由于安全问题。

任何可以查看实例基本属性的人都可以以纯文本形式读取UserData 这意味着,您的JLabPassword将以纯文本形式出现在UserData中,供所有人查看,如果这样的解决方案可行的话。

为解决此问题,应在UserData中使用 SSM 参数,如下所示:

  1. 将 IAM 权限ssm:GetParameter附加到允许实例访问 SSM 参数存储的实例角色/配置文件。

  2. 而不是在参数中的{{resolve:ssm:JLabPassword:1}}上,您可以只传递JLabPassword以便将 SSM 参数的名称传递给UserData ,而不是它的实际值。

  3. UserData中,请使用 AWS CLI get-parameter获取JLabPassword的实际值。

以上确保JLabPassword的值是私有的,并且在UserData的纯文本中不可见。

您的密码参数的默认值缺少服务名称 ( ssm ) 以及单引号。

// What you have:
Password:
  Default: {{resolve:JupyterPassword:1}}
  ...

// What it should be:
Password:
  Default: '{{resolve:ssm:JupyterPassword:1}}'
  ...

更新:您已经修复了问题中的代码。 我的回答和下面的评论解决了你的问题吗? 如果没有,我不确定您还需要什么。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM