AWS Session Manager에 대하여.

참고 영상 : https://youtu.be/mRq0VvXA-j8

Amazon Linux에는 기본적으로 ssm agent가 설치되어있기 때문에 iam role만 있으면 된다.

한편으로는, Amazon linux가 아니라면 ssm agent 별도 설치가 필요.

역할(role) 생성:

  • 해당 역할을 사용할 대상 : EC2

  • 역할(role) 생성시 사용할 정책 중에는 “AmazonEC2RoleforSSM”이라는 정책
  • EC2에 이 role만 부여해주면 됨
  • 실습간에는 EC2를 생성시 SSH포트(22)도 부여하지 않았고 키페어도 사용하지 않음으로 체크하여 생성하였다
  • AWS Systems Manager 콘솔 화면 > Session Manager > 세션 시작
  • bash > sudo -s > 정상 확인
  • cloudwatch 로그그룹과 연결하여 서버 내에서 어떤 유저가 어떤 작업을 했는지에 대한 로그를 기록 가능

SSM + Lambda를 사용하여 EC2 특정시간에 켜고 끄기

  1. iam > 역할생성 >
    1. 역할 사용 대상 : SystemManager
    2. 사용할 정책 : AmazonSSMAutomationRole
    3. 역할 이름 : MySSMAutomationRole
  2. Lambda를 위한 role 생성
    1. 역할 이름 : MyEC2StartStopRole
    2. 인라인 정책 내용 : https://youtu.be/mRq0VvXA-j8?t=420
    3. 1단계에서 생성한 ‘MySSMAutomationRole’ role의 arn 사용
  3. Lambda 생성
    1. 역할 설정시 위 2단계에서 생성한 ‘MyEC2StartStopRole’ role 선택
    2. Labmda 내용 : https://youtu.be/mRq0VvXA-j8?t=488
    3. 파라미터는 타겟 EC2가 가지고 있는 tag의 key, value 그리고 1단계 role ‘MySSMAutomationRole’, 그리고 ‘stop’ 혹은 ‘start’
    4. 이렇게 test를 진행하면 EC2의 시작과 종료 권한을 가지고 있는 lambda가 SSM에 기능을 위임 > session manager에게 ‘MySSMAutomationRole’ role의 arn을 짚어주며 ‘자동화’에 대한 명령을 실행하라고 명령.
  4. CloudWatch 규칙 생성

이 과정을 한번에 쉽게 구축할 수 있도록 만들어놓은 CloudFormation 명세서

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Resource Id
        Parameters:
          - EC2TagKey
          - EC2TagValue
      - Label:
          default: Start/Stop Time
        Parameters:
          - StartTimeInGMT
          - StopTimeInGMT
Parameters:
  EC2TagKey:
    Description: EC2TagKey
    Type: String
    Default: Service
  EC2TagValue:
    Description: EC2TagValue
    Type: String
    Default: test
  StartTimeInGMT:
    Description: Start hour in GMT
    Default: 0
    Type: Number
  StopTimeInGMT:
    Description: Stop hour in GMT
    Default: 9
    Type: Number
Resources:
  AutomationServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ssm.amazonaws.com
                - ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole
      Path: "/"

  EC2OnOffLambdaExeRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: "/"
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "ssm:*"
                  - "tag:*"
                Resource: "*"
              - Effect: Allow
                Action:
                  - "logs:CreateLogGroup"
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"
                Resource: arn:aws:logs:*:*:*
              - Effect: Allow
                Action:
                  - "iam:PassRole"

                Resource: !Sub
                  - "${AutomationServiceRoleArn}"
                  - AutomationServiceRoleArn:
                      Fn::GetAtt:
                        - "AutomationServiceRole"
                        - "Arn"

  StopStartEC2Lambda:
    Type: "AWS::Lambda::Function"
    Properties:
      Handler: "index.handler"
      Role:
        Fn::GetAtt:
          - "EC2OnOffLambdaExeRole"
          - "Arn"
      Runtime: "nodejs12.x"
      # we give the function a large timeout
      # so we can wait for the bucket to be empty
      Timeout: 600
      Code:
        ZipFile: |
          var AWS = require("aws-sdk");
           AWS.config.update({
               region: "ap-northeast-2"
           });
           exports.handler = async function (event, context) {
             console.log("event:",event);
             var ssm = new AWS.SSM();
             var params = {
             DocumentName: (event.action=="stop")?'AWS-StopEC2Instance':'AWS-StartEC2Instance',
             Parameters: {
              'AutomationAssumeRole': [event.rolearn ],
             
            },
             MaxConcurrency: '10' ,
             MaxErrors: '25%',
             TargetParameterName:"InstanceId",
             Targets: [
               {
                 Key: `tag:${event.key}`,
                 Values: [event.value]
               },
             ]
             };
             try
             {
               const result=await ssm.startAutomationExecution(params).promise();
               console.log(result);
             }
             catch(e)
             {
               console.log(e);
             }
           };
  CloudWatchEventStartRule:
    Type: AWS::Events::Rule
    Properties:
      Description: startrule
      ScheduleExpression: !Sub
        - "cron(0 ${StartTimeInGMT} ? * 1-5 *)"
        - StartTimeInGMT: !Ref StartTimeInGMT
      Targets:
        - Arn: !GetAtt StopStartEC2Lambda.Arn
          Id: start-ec2
          Input: !Sub
            - '{"key":"${EC2TagKey}","value":"${EC2TagValue}","rolearn":"${AutomationServiceRoleArn}","action":"start"}'
            - AutomationServiceRoleArn:
                Fn::GetAtt:
                  - "AutomationServiceRole"
                  - "Arn"
  CloudWatchEventStopRule:
    Type: AWS::Events::Rule
    Properties:
      Description: stoprule
      ScheduleExpression: !Sub
        - "cron(0 ${StopTimeInGMT} ? * 1-5 *)" #오전 9시 이전일 경우, 0 ${StopTimeInGMT} ? * 2-6 *
        - StopTimeInGMT: !Ref StopTimeInGMT
      Targets:
        - Arn: !GetAtt StopStartEC2Lambda.Arn
          Id: stop-ec2
          Input: !Sub
            - '{"key":"${EC2TagKey}","value":"${EC2TagValue}","rolearn":"${AutomationServiceRoleArn}","action":"stop"}'
            - AutomationServiceRoleArn:
                Fn::GetAtt:
                  - "AutomationServiceRole"
                  - "Arn"

  PermissionForEventsCallStartLambda:
    Type: AWS::Lambda::Permission
    DependsOn: CloudWatchEventStartRule
    Properties:
      FunctionName:
        Ref: StopStartEC2Lambda
      Action: "lambda:InvokeFunction"
      Principal: "events.amazonaws.com"
      SourceArn:
        Fn::GetAtt:
          - "CloudWatchEventStartRule"
          - "Arn"
  PermissionForEventsCallStopLambda:
    Type: AWS::Lambda::Permission
    DependsOn: CloudWatchEventStopRule
    Properties:
      FunctionName:
        Ref: StopStartEC2Lambda
      Action: "lambda:InvokeFunction"
      Principal: "events.amazonaws.com"
      SourceArn:
        Fn::GetAtt:
          - "CloudWatchEventStopRule"
          - "Arn"

Tags: ,

Categories:

Updated:

Leave a comment