開發與維運

使用運維編排服務配置多臺實例的免密登陸

使用運維編排服務配置多臺實例的免密登陸

運維編排是阿里雲提供的雲上自動化運維服務,能夠自動化管理和執行任務。您可以通過模板來定義執行任務、執行順序、執行輸入和輸出,然後通過執行模板來完成任務的自動化運行。
SSH免密登陸大多用於自動化運維,主要是安全方便自動化管理大批服務器。如果您有大量的實例,期望可以將部分或全部的實例配置成免密登陸。那麼怎麼才能快速的配置實例的免密登陸呢?下面為您介紹通過運維編排服務來快速配置大量實例的免密登陸。

前提條件

  1. 準備ECS實例。如果您還未有實例,請參考入門概念購買ECS實例
  2. 需要配置免密登陸的實例必須擁有相同的用戶名。
  3. 本示例僅支持Linux類型實例。

操作步驟

  1. 登錄運維編排控制檯
  2. 給實例增加新User,如果您的實例內已經有需要做免密配置的用戶,請直接跳到下一步。如果實例內還未有相同的User,您可以使用運維編排的批量操作實例功能,執行相應的增加User腳本。如下所示:

20201201111558.jpg

  1. 創建模版。

本示例為您提供了一個自動化配置實例免密登錄的模板,模版內容請參考附錄一,將模版內容複製進入輸入框後,單擊創建模版。(本模板的主要功能為,選擇並獲取部分實例的公鑰,然後再選擇需要配置免密登錄的實例,將上一步的公鑰配置進指定User下。)20201201103830.jpg

  1. 執行模板。

找到上一步已經創建完成的模板,單擊創建執行 >> 下一步:設置參數
20201201105534.jpg

  1. 輸入參數。選擇實例時可以直接選擇實例,或者根據實例上的標籤選擇實例。如下所示:

20201201112610.jpg

  1. 單擊下一步:確定 >> 創建,確認輸入的參數沒有問題後,就可以執行模版了。

20201201112807.jpg

  1. 等待模版執行成功後,驗證免密配置是否生效。

進入其中一個已經配置了免密登錄的實例。在某一user下,執行ssh 命令。我們就可以不輸入密碼直接進入另一臺實例了。如下所示的例子:進入一個為freelogin的user下,執行ssh ip地址,即進入了另外一臺實例內。此時可以發現免密配置已經生效了。20201201113931.jpg

附錄一:配置免密登陸模版

模板參數介紹

參數名稱 說明
regionId 地域ID。
sourceTarget 做免密登陸配置時,需要獲取免密公鑰的實例。
destinationTarget 需要開通免密登陸的實例。
userName 實例內的用戶名。
rateControl 任務執行的併發比率。
OOSAssumeRole OOS扮演的RAM角色。

模板內容

FormatVersion: OOS-2019-06-01
Description:
  en: 'In the instance, a user is linked without encryption by means of an authorization key.'
  zh-cn: 在實例內,某一用戶通過授權密鑰的方式免密鏈接。
Parameters:
  regionId:
    Type: String
    Description:
      en: The id of region.
      zh-cn: 地域ID。
    AssociationProperty: RegionId
    Default: '{{ ACS::RegionId }}'
  sourceTarget:
    Type: Json
    Description:
      en: Example of obtaining the secret-free public key when configuring the secret-free login.
      zh-cn: 做免密登陸配置時,獲取免密公鑰的實例。
    AssociationProperty: Targets
    AssociationPropertyMetadata:
      ResourceType: 'ALIYUN::ECS::Instance'
      RegionId: regionId
  destinationTarget:
    Type: Json
    Description:
      en: Need to open an instance of password-free login.
      zh-cn: 需要開通免密登陸的實例。
    AssociationProperty: Targets
    AssociationPropertyMetadata:
      ResourceType: 'ALIYUN::ECS::Instance'
      RegionId: regionId
    Default:
      Type: ResourceIds
      ResourceIds: []
  userName:
    Description:
      en: Password-free login username in the instance.
      zh-cn: 實例內的免密登陸的用戶名稱。
    Type: String
  rateControl:
    Description:
      en: Concurrency ratio of task execution.
      zh-cn: 任務執行的併發比率。
    Type: Json
    AssociationProperty: RateControl
    Default:
      Mode: Concurrency
      MaxErrors: 0
      Concurrency: 10
  OOSAssumeRole:
    Description:
      en: The RAM role to be assumed by OOS.
      zh-cn: OOS扮演的RAM角色。
    Type: String
    Default: OOSServiceRole
RamRole: '{{ OOSAssumeRole }}'
Tasks:
  - Name: getSourceInstance
    Description:
      en: Get an instance that needs to be logged in without password.
      zh-cn: 獲取需要被免密登陸的實例。
    Action: 'ACS::SelectTargets'
    Properties:
      ResourceType: 'ALIYUN::ECS::Instance'
      RegionId: '{{ regionId }}'
      Filters:
        - '{{ sourceTarget }}'
    Outputs:
      instanceIds:
        Type: List
        ValueSelector: 'Instances.Instance[].InstanceId'
  - Name: getDestinationInstance
    Description:
      en: Views the ECS instances than to ssh without password.
      zh-cn: 獲取配置免密登陸的實例。
    Action: 'ACS::SelectTargets'
    Properties:
      ResourceType: 'ALIYUN::ECS::Instance'
      RegionId: '{{ regionId }}'
      Filters:
        - '{{ destinationTarget }}'
    Outputs:
      instanceIds:
        Type: List
        ValueSelector: 'Instances.Instance[].InstanceId'
  - Name: generateOrGetPublicKey
    Action: 'ACS::ECS::RunCommand'
    Description:
      en: Generate or get a public key.
      zh-cn: 生成或獲取公共密鑰。
    Properties:
      regionId: '{{ regionId }}'
      commandContent: |-
        #!/bin/bash
        username="{{ username }}"

        if [ $username == root ]; then
            if [ ! -e "/root/.ssh/id_rsa.pub" ]; then
              ssh-keygen -f "/root/.ssh/id_rsa" -P "" >> /dev/null
            fi
            cat /root/.ssh/id_rsa.pub
        else
            if [ ! -e "/home/$username/.ssh/id_rsa.pub" ]; then
                su $username -l -c "ssh-keygen -f /home/$username/.ssh/id_rsa -P '' >> /dev/null"
            fi
            chmod 700 /home/$username/.ssh
            cat /home/$username/.ssh/id_rsa.pub
        fi
      instanceId: '{{ ACS::TaskLoopItem }}'
      commandType: RunShellScript
    Loop:
      RateControl: '{{ rateControl }}'
      Items: '{{ getSourceInstance.instanceIds }}'
      Outputs:
        publicKeys:
          AggregateType: 'Fn::ListJoin'
          AggregateField: publicKey
    Outputs:
      publicKey:
        Type: String
        ValueSelector: invocationOutput
  - Name: converPublicKeyToStr
    Action: 'ACS::ECS::SMCConversionConstantByJqScript'
    Description:
      en: Convert public key to string.
      zh-cn: 將公鑰轉換成字符串。
    Properties:
      parameter:
        'Fn::Jq':
          - First
          - 'join(",")'
          - '{{ generateOrGetPublicKey.publicKeys }}'
      jqScript:
        - '.[0] | .'
        - '.[0] | .'
    Outputs:
      publicKey:
        Type: String
        ValueSelector: 'firstValue | split(",") | join("\n")'
  - Name: authorizedInstances
    Action: 'ACS::ECS::RunCommand'
    Description:
      en: Enable password-free login for users in the instance.
      zh-cn: 開通實例內用戶的免密登陸。
    Properties:
      regionId: '{{ regionId }}'
      commandContent: |-
        #!/bin/bash
        username="{{ username }}"
        publicKey="{{ converPublicKeyToStr.publicKey }}"
        if [ $username == root ]; then
            if [ ! -e "/root/.ssh/id_rsa.pub" ]; then
                ssh-keygen -f "/root/.ssh/id_rsa" -P "" >> /dev/null
            fi
            cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
        else
            if [ ! -e "/home/$username/.ssh/id_rsa.pub" ]; then
                su $username -l -c "ssh-keygen -f /home/$username/.ssh/id_rsa -P '' >> /dev/null"
            fi
            chmod 700 /home/$username/.ssh
            cat /home/$username/.ssh/id_rsa.pub >> /home/$username/.ssh/authorized_keys
        fi
        if [ $username == root ]; then
        cat >> /root/.ssh/authorized_keys << eof
        $publicKey
        eof
        else
        cat >> /home/$username/.ssh/authorized_keys << eof
        $publicKey
        eof
        fi
      instanceId: '{{ ACS::TaskLoopItem }}'
      commandType: RunShellScript
    Loop:
      RateControl: '{{ rateControl }}'
      Items: '{{ getDestinationInstance.instanceIds }}'
      Outputs:
        commandOutputs:
          AggregateType: 'Fn::ListJoin'
          AggregateField: commandOutput
    Outputs:
      commandOutput:
        Type: String
        ValueSelector: invocationOutput
Outputs:
  commandOutputs:
    Type: List
    Value: '{{ generateOrGetPublicKey.publicKeys }}'

Leave a Reply

Your email address will not be published. Required fields are marked *