Hyper-v 쿠버네티스 클러스터에서 각 서버에 접근할 때 비밀번호 없이 로그인하기 위해 ssh key를 생성하고 key를 각 서버에 자동 배포하기 위해 작성한 쉘스크립트 코드이다.
SSH Key
서버에 접속할 때 비밀번호 대신 key를 제출하는 방식이다.
사용하는 목적
- 비밀번호보다 높은 수준의 보안을 필요로 할 때
- 로그인 없이 자동으로 서버에 접속 할 때
SSH Key가 동작하는 방식
SSH Key는 공개키(public key)와 비공개 키(private key)로 이루어 진다.
키를 생성하면 공개키와 비공개키가 만들어진다. 이 중에 비공개키는 로컬 머신에 위치해야 하고, 공개키는 리모트 머신에 위치해야 한다. (로컬 호스트는 SSH Client, 원격 호스트는 SSH Server가 설치된 서버를 의미한다)
로컬 호스트의 어카운트에 있는 ~/.ssh/id_rsa.pub
키파일의 내용을 원격 호스트 어카운트의 ~/.ssh
디렉토리에 있는 authorized_keys 에 복사한다.
정리하면, SSH Server의 authorized_keys의 내용이 SSH Client의 id_rsa.pub 파일과 같아야 한다. ssh 접속을 할 때 id_rsa 파일과 authorized_keys 파일의 내용을 비교한다.
아래와 같이 서버에 public key를 카피해 놓았다면 원격 호스트에 로그인 할 어카운트의 암호 없이 로그인이 가능하다.
[ssh_key_sharing.sh]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| export CLUSTER_HOSTS=(vm1 vm2 vm3 vm4 vm5 vm6 vm7 vm8 vm9)
export HOME_DIR_PATH=/home/$USER
# sshd_config 변경
for i in ${!CLUSTER_HOSTS[*]}; do ssh woobin@${CLUSTER_HOSTS[$i]} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "sudo dnf install -y sshpass && sudo sed -i -e 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config && sudo systemctl restart sshd" &> /dev/null; done
# ssh key 생성
echo -e ">> Enter Password:"; read -s PASSWD; for i in ${!CLUSTER_HOSTS[*]}; do echo "i[$i]: [${CLUSTER_HOSTS[$i]}]"; sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$i]} "mkdir -p $HOME_DIR_PATH/.ssh; echo -e 'n\n' | ssh-keygen -t rsa -f $HOME_DIR_PATH/.ssh/id_rsa -q -N ''; cp $HOME_DIR_PATH/.ssh/id_rsa.pub $HOME_DIR_PATH/.ssh/authorized_keys; chmod 700 $HOME_DIR_PATH/.ssh" &> /dev/null; done
# ssh key 공유
echo -e ">> Enter Password:"; read -s PASSWD; for i in ${!CLUSTER_HOSTS[*]}; do echo "i[$i]: [${CLUSTER_HOSTS[$i]}]"; for j in ${!CLUSTER_HOSTS[*]}; do echo "j[$j]: [${CLUSTER_HOSTS[$i]}] -> [${CLUSTER_HOSTS[$j]}]"; sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$i]} "sshpass -p $PASSWD ssh-copy-id -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$j]} &> /dev/null" &> /dev/null; done; done
# 체크
for i in ${CLUSTER_HOSTS[*]}; do ssh ${CLUSTER_HOSTS[$i]} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "ls -al .ssh"; done
|
코드 설명
ssh key 생성
1
| echo -e ">> Enter Password:"; read -s PASSWD; for i in ${!CLUSTER_HOSTS[*]}; do echo "i[$i]: [${CLUSTER_HOSTS[$i]}]"; sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$i]} "mkdir -p $HOME_DIR_PATH/.ssh; echo -e 'n\n' | ssh-keygen -t rsa -f $HOME_DIR_PATH/.ssh/id_rsa -q -N ''; cp $HOME_DIR_PATH/.ssh/id_rsa.pub $HOME_DIR_PATH/.ssh/authorized_keys; chmod 700 $HOME_DIR_PATH/.ssh" &> /dev/null; done
|
아래부터는 각 부분에 대한 설명입니다.
1
| echo -e ">> Enter Password:";
|
- ”» Enter Password:” 메시지를 출력합니다.
- 사용자로부터 비밀번호를 읽어서
PASSWD
변수에 저장합니다. s
옵션은 입력한 비밀번호가 화면에 표시되지 않도록 합니다.
1
| `for i in ${!CLUSTER_HOSTS[*]}; do`
|
- 배열
CLUSTER_HOSTS
의 모든 인덱스를 순회하는 루프를 시작합니다.
1
| echo "i[$i]: [${CLUSTER_HOSTS[$i]}]";
|
- 순회 중인 인덱스
i
와 해당 인덱스에 위치한 CLUSTER_HOSTS
배열의 요소를 출력합니다.
1
| sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${CLUSTER_HOSTS[$i]}
|
sshpass
명령어를 사용하여 비밀번호를 제공하고, ssh
명령을 통해 원격 호스트에 연결합니다.$PASSWD
변수에 저장된 비밀번호를 p
옵션으로 전달합니다.-o UserKnownHostsFile=/dev/null
옵션은 호스트 키를 known_hosts 파일에 저장하지 않도록 합니다. /dev/null은 특수 파일로, 데이터를 버리는데 사용됩니다.-o StrictHostKeyChecking=no
옵션은 호스트 키의 유효성을 검사하지 않도록 합니다. 일반적으로 클라이언트가 원격 서버의 호스트 키와 일치하는지 확인하며, 일치하지 않으면 경고를 표시하고 연결을 거부합니다. 그러나 이 옵션을 사용하면 호스트 키 검사를 건너뛰고 연결을 허용하게 됩니다.${CLUSTER_HOSTS[$i]}
는 현재 순회 중인 인덱스 i
에 해당하는 원격 호스트 주소를 사용합니다.
1
| "mkdir -p $HOME_DIR_PATH/.ssh; echo -e 'n\n' | ssh-keygen -t rsa -f $HOME_DIR_PATH/.ssh/id_rsa -q -N ''; cp $HOME_DIR_PATH/.ssh/id_rsa.pub $HOME_DIR_PATH/.ssh/authorized_keys; chmod 700 $HOME_DIR_PATH/.ssh" &> /dev/null;
|
- 원격 호스트에 로그인한 후 수행할 명령어들입니다. 여러 명령어를 세미콜론(
;
)으로 구분하여 순차적으로 실행합니다. mkdir -p $HOME_DIR_PATH/.ssh;
은 원격 호스트에서 .ssh
디렉토리를 생성합니다. p
옵션은 이미 디렉토리가 존재하면 무시하도록 합니다.echo -e 'n\n' | ssh-keygen -t rsa -f $HOME_DIR_PATH/.ssh/id_rsa -q -N '';
echo -e 'n\n' |
: ssh-keygen 명령을 실행할 때 기존 키 파일이 존재하는 경우에 대한 덮어쓰기 여부를 묻는 메시지가 나오는 것을 피하는 것입니다. echo -e ‘n\n’ 명령을 통해 “n”이라는 문자를 출력하고 줄 바꿈을 추가하여, ssh-keygen 명령이 “n” 입력을 받아 덮어쓰기를 거부하도록 하는 것입니다.-t rsa
: RSA 알고리즘을 사용하여 키를 생성한다는 것을 나타냅니다. RSA는 공개키 암호화 방식으로 널리 사용됩니다.-f $HOME_DIR_PATH/.ssh/id_rsa
: 생성할 개인키와 공개키의 파일 이름과 경로를 지정합니다.- ssh key가 저장되는 기본 경로는 로그인 한 사용자의 홈디렉토리 아래에 .ssh입니다. SSH Client는 기본적으로 이 디렉토리에 있는 키를 이용해서 인증을 시도합니다. 여기서는 위에서 지정한 HOME_DIR_PATH/.ssh 경로에 생성하며, 생성되는 파일은 아래와 같습니다.
- id_rsa: private key, 절대로 타인에게 노출되면 안된다.
- id_rsa.pub: public key, 접속하려는 리모트 머신의 authorized_keys에 입력한다.
- authorized_keys: .ssh 디렉토리 아래에 위치하면서 id_rsa.pub 키의 값을 저장한다.
-q
: quiet 모드로 작동하게 합니다. 이 옵션을 사용하면 사용자 입력을 최소화하고 진행 과정에서 메시지를 표시하지 않습니다.-N ''
: 개인키에 설정할 암호를 지정합니다. 여기서는 빈 문자열(''
)을 사용하여 암호를 설정하지 않도록 합니다. 암호를 설정하지 않으면 SSH 키를 사용할 때 암호를 입력하지 않아도 됩니다.
cp $HOME_DIR_PATH/.ssh/id_rsa.pub $HOME_DIR_PATH/.ssh/authorized_keys;
은 공개 키를 authorized_keys
파일에 복사합니다. 이렇게 하면 비밀번호 없이 원격 호스트에 로그인할 수 있게 됩니다.chmod 700 $HOME_DIR_PATH/.ssh
는 매우 중요한 보안 정보가 담긴 디렉토리 입니다. 따라서 퍼미션 설정을 해줘야 합니다. 해당 디렉토리가 소유자만 읽기, 쓰기, 실행이 가능하도록 합니다.&> /dev/null;
는 모든 출력을 무시하고 실행 결과를 /dev/null
로 보냅니다. 즉, 실행 결과를 출력하지 않습니다.
ssh key 공유
1
| echo -e ">> Enter Password:"; read -s PASSWD; for i in ${!CLUSTER_HOSTS[*]}; do echo "i[$i]: [${CLUSTER_HOSTS[$i]}]"; for j in ${!CLUSTER_HOSTS[*]}; do echo "j[$j]: [${CLUSTER_HOSTS[$i]}] -> [${CLUSTER_HOSTS[$j]}]"; sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$i]} "sshpass -p $PASSWD ssh-copy-id -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$j]} &> /dev/null" &> /dev/null; done; done
|
아래부터는 각 부분에 대한 설명입니다.
1
| for i in ${!CLUSTER_HOSTS[*]}; do echo "i[$i]: [${CLUSTER_HOSTS[$i]}]"; for j in ${!CLUSTER_HOSTS[*]}; do echo "-- j[$j]: [${CLUSTER_HOSTS[$i]}] -> [${CLUSTER_HOSTS[$j]}]";
|
- 중첩 for-loop를 통해 모든 클러스터에 대해 진행합니다.
1
| sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${CLUSTER_HOSTS[$i]}
|
- 현재 i번째 인덱스에 해당하는 원격 호스트에서 아래의 작업을 진행합니다.
1
| "sshpass -p $PASSWD ssh-copy-id -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${CLUSTER_HOSTS[$j]} &> /dev/null" &> /dev/null;
|
ssh-copy-id
: SSH 공개 키를 원격 호스트에 복사합니다.-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
: 호스트 키 확인 및 기록을 하지 않도록 설정합니다.&> /dev/null
: 표준 출력과 표준 에러를 /dev/null로 리다이렉트하여 출력을 무시합니다.