使用运维编排服务配置多台实例的免密登陆
运维编排是阿里云提供的云上自动化运维服务,能够自动化管理和执行任务。您可以通过模板来定义执行任务、执行顺序、执行输入和输出,然后通过执行模板来完成任务的自动化运行。
SSH免密登陆大多用于自动化运维,主要是安全方便自动化管理大批服务器。如果您有大量的实例,期望可以将部分或全部的实例配置成免密登陆。那么怎么才能快速的配置实例的免密登陆呢?下面为您介绍通过运维编排服务来快速配置大量实例的免密登陆。
前提条件
- 准备ECS实例。如果您还未有实例,请参考入门概念购买ECS实例
- 需要配置免密登陆的实例必须拥有相同的用户名。
- 本示例仅支持Linux类型实例。
操作步骤
- 登录运维编排控制台。
- 给实例增加新User,如果您的实例内已经有需要做免密配置的用户,请直接跳到下一步。如果实例内还未有相同的User,您可以使用运维编排的批量操作实例功能,执行相应的增加User脚本。如下所示:
- 创建模版。
本示例为您提供了一个自动化配置实例免密登录的模板,模版内容请参考附录一,将模版内容复制进入输入框后,单击创建模版。(本模板的主要功能为,选择并获取部分实例的公钥,然后再选择需要配置免密登录的实例,将上一步的公钥配置进指定User下。)
- 执行模板。
找到上一步已经创建完成的模板,单击创建执行 >> 下一步:设置参数。
- 输入参数。选择实例时可以直接选择实例,或者根据实例上的标签选择实例。如下所示:
- 单击下一步:确定 >> 创建,确认输入的参数没有问题后,就可以执行模版了。
- 等待模版执行成功后,验证免密配置是否生效。
进入其中一个已经配置了免密登录的实例。在某一user下,执行ssh 命令。我们就可以不输入密码直接进入另一台实例了。如下所示的例子:进入一个为freelogin的user下,执行ssh ip地址,即进入了另外一台实例内。此时可以发现免密配置已经生效了。
附录一:配置免密登陆模版
模板参数介绍
参数名称 | 说明 |
---|---|
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 }}'