

# 공유 Linux AMI 생성을 위한 권장 사항
<a name="building-shared-amis"></a>

AMI의 안정성을 높이고 공격 표면을 최소화하려면 다음 지침을 사용하세요.

**중요**  
어떤 보안 지침도 포괄적일 수는 없습니다. 공유 AMI를 구축할 때는 민감한 데이터의 유출 가능성에 특히 유의하고, 충분한 시간을 할애하여 검토하세요.

**Topics**
+ [루트 사용자의 암호 방식 원격 로그인 비활성화](#public-amis-disable-password-logins-for-root)
+ [로컬 루트 액세스 비활성화](#restrict-root-access)
+ [SSH 호스트 키 페어 삭제](#remove-ssh-host-key-pairs)
+ [퍼블릭 키 자격 증명 설치](#public-amis-install-credentials)
+ [sshd DNS 확인 비활성화(선택 사항)](#public-amis-disable-ssh-dns-lookups)
+ [민감한 데이터 제거](#public-amis-protect-yourself)

AWS Marketplace용 AMI를 구축하는 경우에는 *AWS Marketplace 판매자 가이드*의 [AMI 구축 모범 사례](https://docs.aws.amazon.com/marketplace/latest/userguide/best-practices-for-building-your-amis.html)에서 지침, 정책 및 모범 사례를 참조하세요.

## 루트 사용자의 암호 방식 원격 로그인 비활성화
<a name="public-amis-disable-password-logins-for-root"></a>

퍼블릭 AMI에 대하여 고정 루트 암호를 사용하면 보안 위험을 촉진하는 계기가 될 수 있습니다. 고객에게 최초 로그인 시 암호 변경을 알린다 해도 여기에만 의존한다면 어느 정도의 오용 가능성은 여전히 존재합니다.

이런 문제를 해결하려면 루트 사용자의 암호 방식 원격 로그인을 비활성화합니다.

**루트 사용자의 암호 방식 원격 로그인 비활성화**

1. 텍스트 편집기로 `/etc/ssh/sshd_config` 파일을 열고 다음 열을 검색합니다.

   ```
   #PermitRootLogin yes
   ```

1. 해당 열을 다음과 같이 변경합니다.

   ```
   PermitRootLogin without-password
   ```

   이 구성 파일의 저장 위치는 배포에 따라서 혹은 OpenSSH를 실행하지 않는 경우 달라질 수 있습니다. 이 경우에는 관련 문서를 참조하세요.

## 로컬 루트 액세스 비활성화
<a name="restrict-root-access"></a>

공유 AMI를 사용할 때는 직접 루트 로그인을 비활성화하는 것이 모범 사례입니다. 이렇게 하려면 실행 중인 인스턴스에 로그인하여 다음 명령을 사용합니다.

```
[ec2-user ~]$ sudo passwd -l root
```

**참고**  
이 명령은 `sudo` 사용에는 영향을 주지 않습니다.

## SSH 호스트 키 페어 삭제
<a name="remove-ssh-host-key-pairs"></a>

 퍼블릭 AMI에서 유래된 AMI를 공유할 계획이라면 `/etc/ssh`에 저장된 현재 SSH 호스트 키 페어를 삭제하십시오. 이 작업은 다른 사용자가 이 AMI를 사용해 인스턴스를 시작할 때 SSH에서 반드시 새로운 고유 SSH 키 페어를 생성하도록 하기 때문에 "중간자 공격" 가능성을 낮추고 보안을 향상시켜 줍니다.

시스템에서 다음의 키 파일을 모두 제거합니다.
+  ssh\$1host\$1dsa\$1key 
+  ssh\$1host\$1dsa\$1key.pub 
+  ssh\$1host\$1key 
+  ssh\$1host\$1key.pub 
+  ssh\$1host\$1rsa\$1key 
+  ssh\$1host\$1rsa\$1key.pub 
+ ssh\$1host\$1ecdsa\$1key
+ ssh\$1host\$1ecdsa\$1key.pub
+ ssh\$1host\$1ed25519\$1key
+ ssh\$1host\$1ed25519\$1key.pub

이런 파일은 다음 명령을 실행하여 안전하게 제거할 수 있습니다.

```
[ec2-user ~]$ sudo shred -u /etc/ssh/*_key /etc/ssh/*_key.pub
```

**주의**  
**shred**와 같은 보안 삭제 유틸리티는 스토리지 미디어에서 파일의 사본을 모두 제거하지 못할 수 있습니다. 파일 시스템(Amazon Linux default ext4 포함), 스냅샷, 백업, RAID 및 임시 캐싱을 저널링하여 파일의 숨겨진 사본이 생성될 수 있습니다. 자세한 내용은 [공유 설명서](https://www.gnu.org/software/coreutils/manual/html_node/shred-invocation.html)를 참조하세요.

**중요**  
퍼블릭 AMI의 현재 SSH 호스트 키 페어를 제거하지 않은 경우, 기본적인 자체 감사 과정에서 소유자를 비롯해 해당 AMI를 사용해 인스턴스를 실행하는 모든 사용자에게 잠재적인 보안 위험을 알리는 메시지가 표시됩니다. 이 AMI는 단기적인 유예 기간 후 프라이빗 상태로 변경됩니다.

## 퍼블릭 키 자격 증명 설치
<a name="public-amis-install-credentials"></a>

암호를 사용한 AMI 로그인을 비활성화했다면 이제 다른 방식으로 사용자가 로그인할 수 있도록 해야 합니다.

Amazon EC2에서는 인스턴스를 시작할 때 사용자가 퍼블릭/프라이빗 키 페어 이름을 설정하는 것을 허용합니다. 유효한 키 페어 이름이 `RunInstances` API 호출(또는 명령출 API 도구)로 전송되면, 퍼블릭 키(Amazon EC2에서 `CreateKeyPair` 또는 `ImportKeyPair`로의 호출이 이루어진 후에 서버에 저장하는 키 페어의 일부)를 인스턴스 메타데이터에 대한 HTTP 쿼리를 통해 인스턴스에서 사용할 수 있게 됩니다.

SSH을 통해 로그인하려면 AMI에서 반드시 부팅 시 키 값을 회수하고 이 값을 `/root/.ssh/authorized_keys`에 (또는 AMI 상의 다른 사용자 계정의 값) 첨부해야 합니다. 사용자는 루트 암호 없이 키 페어를 사용하여 AMI의 인스턴스를 실행할 수 있습니다.

Amazon Linux 및 Ubuntu를 포함한 대부분의 배포판에서는 지정된 사용자에 대한 퍼블릭 키 자격 증명을 첨가할 때 `cloud-init` 패키지를 사용합니다. 사용하는 배포판에서 `cloud-init`를 지원하지 않는 경우, 시스템 시작 스크립트(예: `/etc/rc.local`)에 다음 코드를 추가하여 시작 시 루트 사용자에 대해 지정한 퍼블릭 키를 가져오도록 설정할 수 있습니다.

**참고**  
다음 예에서 IP 주소 http://169.254.169.254/는 링크-로컬 주소이며 인스턴스에서만 유효합니다.

------
#### [ IMDSv2 ]

```
if [ ! -d /root/.ssh ] ; then
        mkdir -p /root/.ssh
        chmod 700 /root/.ssh
fi
# Fetch public key using HTTP
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key > /tmp/my-key
if [ $? -eq 0 ] ; then
        cat /tmp/my-key >> /root/.ssh/authorized_keys
        chmod 700 /root/.ssh/authorized_keys
        rm /tmp/my-key
fi
```

------
#### [ IMDSv1 ]

```
if [ ! -d /root/.ssh ] ; then
        mkdir -p /root/.ssh
        chmod 700 /root/.ssh
fi
# Fetch public key using HTTP
curl http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key > /tmp/my-key
if [ $? -eq 0 ] ; then
        cat /tmp/my-key >> /root/.ssh/authorized_keys
        chmod 700 /root/.ssh/authorized_keys
        rm /tmp/my-key
fi
```

------

 이 작업은 어떤 사용자에게나 적용할 수 있으며, `root` 사용자로 제한할 필요가 없습니다.

**참고**  
이 AMI를 기반으로 인스턴스를 다시 번들링하면 시작했을 때 사용했던 키가 포함됩니다. 키가 포함되는 것을 방지하려면 `authorized_keys` 파일의 내용을 지우거나 파일을 삭제하는 방법, 또는 재번들링 시 파일을 포함 제외해야 합니다.

## sshd DNS 확인 비활성화(선택 사항)
<a name="public-amis-disable-ssh-dns-lookups"></a>

sshd DNS 확인을 비활성화하면 sshd 보안성은 약간 저하됩니다. 하지만 DNS 확인이 실패했을 때에도 SSH 로그인이 가능하게 해 줍니다. sshd 확인을 비활성화하면 DNS 확인 오류 시 모든 로그인이 금지됩니다.

**sshd DNS 확인 비활성화**

1. 텍스트 편집기로 `/etc/ssh/sshd_config` 파일을 열고 다음 열을 검색합니다.

   ```
   #UseDNS yes
   ```

1. 해당 열을 다음과 같이 변경합니다.

   ```
   UseDNS no
   ```

**참고**  
이 구성 파일의 저장 위치는 배포에 따라서 혹은 OpenSSH를 실행하지 않는 경우 달라질 수 있습니다. 이 경우에는 관련 문서를 참조하세요.

## 민감한 데이터 제거
<a name="public-amis-protect-yourself"></a>

공유하는 AMI에는 민감한 데이터나 소프트웨어를 포함하지 않는 것이 권장됩니다. 공유 AMI를 시작하는 사용자가 이런 AMI를 재번들링하여 본인 소유로 등록할 수 있기 때문입니다. 다음 지침에 따라 그냥 지나치기 쉬운 보안 위험에 대처하세요.
+ `--exclude directory`에서 `ec2-bundle-vol` 옵션을 사용해 번들에 포함하지 않아야 할 보안 정보가 담긴 디렉터리나 하위 디렉터리를 선택하지 않는 방법을 권장합니다. 특히, 이미지를 번들링할 때 모든 사용자 소유 SSH 퍼블릭/프라이빗 키 페어와 SSH `authorized_keys` 파일을 제외하세요. Amazon 퍼블릭 AMI는 이들 파일을 루트 사용자의 경우 `/root/.ssh`에 저장하고 일반 사용자의 경우 `/home/user_name/.ssh/`에 저장합니다. 자세한 내용은 [ec2-bundle-vol](ami-tools-commands.md#ami-bundle-vol) 섹션을 참조하세요.
+ 번들링 전에는 항상 셸 기록을 삭제합니다. 동일한 AMI로 하나 이상의 번들을 업로드하려고 시도하면 셸 기록에 액세스 키가 포함됩니다. 다음 명령은 인스턴스 내에서 번들링을 실시하기 전 마지막 단계로 실행해야 합니다.

  ```
  [ec2-user ~]$ shred -u ~/.*history
  ```
**주의**  
위 경고에서 설명한 **shred**의 제한은 여기에도 적용됩니다.  
bash는 종료 시점에서 현재 세션의 이력을 디스크에 기록한다는 점을 유의하세요. `~/.bash_history`를 삭제한 후 인스턴스에서 로그아웃했다가 다시 로그인할 경우 `~/.bash_history`가 다시 생성되고 이전 세션에서 실행한 모든 명령이 포함되어 있는 것을 알 수 있습니다.  
bash 이외의 다른 프로그램도 디스크에 이력을 기록하므로 불필요한 DOT 파일 및 DOT 디렉터리를 삭제 또는 제외하도록 주의하세요.
+ 실행 중인 인스턴스를 번들링하려면 프라이빗 키와 X.509 인증서가 필요합니다. 이런 정보와 다른 자격 증명은 번들링에 포함되지 않은 장소(예: 인스턴스 저장소)에 따로 보관하세요.