Dilluti0n의 블로그

셸 스크립트는 강력한 도구지만 stdin 을 비활성화하고 프롬프트로 입력을 받는 많은 대화형 cli의 경우엔 자동화하기 취약하다. 가장 많이 겪었을 만한 상황은 sudo(8) 로 실행해야 하는 프로그램을 자동화하고 싶은 경우다. 보통 스크립트는 그냥 작성하고 해당 스크립트를 sudo 로 호출하는 방식을 사용하는데, 이 도구를 사용하면 비밀번호 입력도 자동화 할 수 있다! 물론 보안상 권장되지는 않지만…

예를 들어서 openconnect 로 vpn 에 접속해야 하는 상황에…

#!/usr/bin/expect -f

set timeout 15
set username "yourusername"
set password "yourpassword"
set otp [exec oathtool --totp -b "somebase64secertkey"]

spawn sudo openconnect --protocol=gp --user=${username} vpn.example.com

expect "Password: "
send -- "${password}\r"

expect "Challenge: "
send -- "${otp}\r"

interact

로 패스워드 입력 & otp 챌린지까지 한큐에 끝낼 수 있다. vpn 에 연결할때마다 휴대폰을 들어서 앱을 뒤적거리고 otp 키를 한땀한땀 입력해야 하는데, oathtool 이 secret key 로부터 otp 키를 만들어 주고 그걸 openconnect 프롬프트에 입력하는 과정까지 한번에 끝낼 수 있는 것이다.

otp secret key 를 평문으로 파일시스템에 남기는 건 보안적으로 바람직하지 않는데(특히 otp 의 의도 자체를 생각해 본다면…), GPG 를 통해 암호화하고 사용할 때만 마스터 키로 해제하는 방법을 생각할 수 있겠다. 해당 과정을 체계적으로 정리한 pass 라는 패스워드 관리 유틸리티도 있다.

사실 프로그램이 스크립트 친화적이라면 필요없는 프로그램이지만, 패스워드 입력은 보안 측면에서 stdin 을 막아놓고 터미널에서 바로 입력받는 식으로 하는 프로그램이 많아서, 이를 우회하는 느낌이다.

스크립팅 언어로는 tcl 을 사용하는데, 위에서 보듯 단순하고 원하는 걸 하는데에 별다른 어려움은 없지만 익숙한 언어를 쓰고 싶다면 파이썬 구현체인 pexpect 사용을 추천한다.