명령 패턴과 sudo

토큰은 등록해 둔 명령만 실행할 수 있습니다. 허용된 명령 규칙은 root로 실행될 명령이 아니라 파이프라인이 제출한 명령줄과 비교되므로, sudo로 시작하는 명령의 규칙에도 sudo가 들어가야 합니다.

권한이 필요한 명령을 통과시키려면 서로 다른 두 가지 권한이 필요합니다. 명령줄을 허용하는 규칙, 그리고 서버에서 권한을 상승시킬 자격입니다. 이 둘은 서로 다른 곳에서 설정되고 규약도 정반대여서, 자동화된 배포가 이 지점에서 멈추는 가장 흔한 원인이 됩니다.

허용된 명령은 토큰마다 설정합니다. API 접근 토큰서비스 토큰을 참고하세요.

명령 규칙은 어떻게 매칭되나요

  • 규칙은 제출한 명령줄과 처음부터 끝까지 비교됩니다. 일부만 일치하는 것으로는 부족합니다.
  • 와일드카드는 * 하나뿐이며, 임의의 문자열을 의미합니다.
  • 명령줄이 &&, ||, |, ;, 리다이렉션으로 여러 명령을 연결하면 각 조각이 따로 매칭되며, 모든 조각이 어떤 규칙에든 허용되어야 합니다.
  • 비교하기 전에 따옴표가 제거되고 여분의 공백이 하나로 합쳐지므로, echo "hello world"echo hello world로, 공백이 두 개인 echo helloecho hello로 매칭됩니다.
  • 맞는 규칙이 없으면 요청은 api_token_acl_not_allowed로 거부되고 서버에서는 아무것도 실행되지 않습니다.

끝의 와일드카드는 인자를 요구합니다

*로 끝나는 규칙은 인자를 최소 1개 요구합니다. 와일드카드 앞의 공백도 규칙의 일부이기 때문입니다.

규칙허용불허
dockerdockerdocker ps
docker *docker ps, docker compose up -ddocker (인자 없음)
systemctl status *systemctl status nginxsystemctl restart nginx

인자가 없는 형태와 인자가 있는 형태를 모두 허용하려면 dockerdocker * 두 규칙을 등록하세요.

규칙의 사용자와 그룹

각 규칙은 어떤 시스템 사용자와 그룹이 그 명령을 실행할 수 있는지도 지정합니다.

토큰 종류유저명 빈값유저명 *유저명 deploy
API 접근 토큰토큰 소유자만모든 사용자deploy
서비스 토큰모든 사용자모든 사용자deploy

서비스 토큰은 사람이 아니라 애플리케이션에 속하므로 기준이 될 소유자가 없습니다. 서비스 토큰 규칙에서 유저명을 비워 두면 모든 시스템 사용자에게 허용됩니다. 하나의 계정으로 고정하려면 유저명을 명시하세요.

실행하는 그대로 규칙을 작성하세요

규칙은 root로 실행될 명령이 아니라 제출한 줄과 비교되므로, 권한이 필요한 명령의 규칙에는 sudo가 포함되어야 합니다.

실행하는 명령허용하는 규칙허용하지 않는 규칙
sudo systemctl restart nginxsudo systemctl restart nginxsystemctl restart nginx
sudo -n systemctl restart nginxsudo -n systemctl restart nginxsudo systemctl restart nginx
sudo docker pssudo docker *docker *

sudo Xsudo -n X는 서로 다른 명령줄이므로 각각 규칙이 필요합니다. 파이프라인이 실제로 실행하는 줄을 그대로 등록하세요. 작업이 비대화형 실행을 위해 -n을 붙이거나 다른 계정으로 실행하려고 -u를 붙인다면 그 플래그도 비교 대상 줄의 일부입니다.

sudo 와일드카드가 위험한 이유

sudo * 규칙은 제한 없는 root 권한을 부여합니다. 와일드카드는 따옴표를 넘어 매칭되므로 이 규칙은 sudo bash -c "rm -rf /"도 허용합니다. sudo bash -c *sudo sh -c *도 마찬가지입니다.

대신 필요한 권한 명령을 하나씩 나열하세요.

sudo systemctl restart nginx
sudo systemctl reload nginx

명령 규칙과 sudo 정책은 정반대입니다

Alpacon에는 명령 패턴을 쓰는 곳이 하나 더 있습니다. 누가 어떤 서버에서 권한을 상승시킬 수 있는지 정하는 sudo 정책입니다. 두 가지는 비슷해 보이지만 서로 다른 시점에 서로 다른 문자열과 비교되므로, 같은 명령이라도 각각 정반대의 패턴이 필요합니다.

허용된 명령 규칙sudo 정책
적용 대상토큰 하나선택한 서버의 Alpacon 사용자
검사 시점명령이 서버로 전달되기 전서버가 Alpacon에 권한 상승 승인을 요청할 때
비교 대상작성한 줄 그대로 (sudo 포함)root로 실행되는 명령 (sudo가 이미 제거된 상태)
sudo systemctl restart nginx의 패턴sudo systemctl restart nginxsystemctl restart nginx
패턴 앞의 sudo필요함저장할 때 거부됨
맞는 것이 없을 때요청 거부, 아무것도 실행되지 않음권한 상승 거부, sudo가 오류로 종료

sudo로 시작하는 패턴으로 sudo 정책을 저장하면 sudo_policy_pattern_has_sudo_prefix로 실패합니다. 의도된 동작입니다. 그런 패턴은 어떤 명령과도 매칭될 수 없으므로, 몇 주 뒤에 조용히 거부되는 것보다 작성하는 즉시 거부하는 편이 낫습니다.

sudo 정책을 만들고 사용하는 방법은 sudo with MFA를 참고하세요.

토큰이 sudo를 실행하면

허용된 명령 규칙을 통과했다는 것은 명령이 전달되었다는 의미일 뿐입니다. 권한 상승은 서버에서 sudo가 실행되는 시점에 다시 판단됩니다.

서비스 토큰. 허용된 명령 규칙을 통과하면 권한 상승은 명령의 위험도 평가로 자동 결정됩니다. Critical 미만은 모두 허용되고 CriticalSUDO_RISK_DENIED로 거부됩니다. 위험도를 평가하지 못한 명령도 허용되므로, 위험도 평가에 장애가 생겨도 파이프라인이 멈추지 않습니다. 승인 대기열에 올라가지 않는데, 무인 파이프라인은 승인 요청에 답할 수 없기 때문입니다. 자동으로 허용된 권한 상승은 모두 Sudo위험도가 낮은 명령 유형으로, 토큰을 소유한 애플리케이션 이름으로 기록됩니다.

sudo 정책은 서비스 토큰에 적용되지 않습니다. sudo 정책의 대상은 Alpacon 사용자인데 서비스 토큰은 사용자가 아닙니다. 정책을 작성해도 위 결과는 달라지지 않습니다.

관리자는 이 기준을 더 좁힐 수 있습니다. 워크스페이스가 Critical보다 낮은 위험도부터 거부하도록 설정할 수 있습니다. 다만 토큰이 사람의 승인을 기다리게 만들 수는 없습니다.

부여할 sudo 권한 자체가 없습니다. 토큰 scope 카탈로그의 어떤 리소스도 sudo 작업을 제공하지 않으므로, 권한 상승은 애플리케이션의 역할이나 토큰 scope에서 켜는 것이 아닙니다. 허용된 명령 항목과 명령의 위험도 평가가 결정합니다.

API 접근 토큰은 다릅니다. 개인 API 접근 토큰만으로는 권한을 상승시킬 수 없습니다. sudo scope가 포함되고 sudo 정책이 적용되는 작업 세션 안에서 실행하거나, 해당 작업을 서비스 토큰으로 옮기세요.

자체 호스팅(self-hosted) 배포에서는 토큰의 권한 상승이 기본적으로 활성화되어 있지 않으며 sudoSUDO_COMMAND_NOT_AUTHORIZED로 거부됩니다. 사용 중인 배포에서 활성화되어 있는지 관리자에게 문의하세요.

거부 메시지

권한 상승이 거부되면 터미널에 Alpacon denied this sudo command (CODE).가 출력되고 sudo는 0이 아닌 상태로 종료됩니다.

코드의미조치
SUDO_RISK_DENIED명령이 Critical로 평가되었거나, 워크스페이스가 허용하는 위험도를 넘었습니다.명령을 더 좁게 나누거나, 승인을 받는 작업 세션으로 실행하세요.
SUDO_COMMAND_NOT_AUTHORIZED이 배포에서는 토큰의 권한 상승이 활성화되어 있지 않습니다.자체 호스팅 기본값입니다. 관리자에게 문의하세요.
SUDO_NO_WORKSESSION_POLICY이 명령에 매칭되는 sudo 정책이 없습니다.서비스 토큰을 쓰거나, sudo 정책이 적용되는 작업 세션 안에서 실행하세요.
SUDO_POLICY_MFA_REQUIREDsudo 정책은 매칭되었지만 MFA를 요구하며, 무인 작업은 MFA를 완료할 수 없습니다.MFA 확인을 건너뛸 수 있는 작업 세션에 정책을 연결하세요.
WORK_SESSION_SCOPE_NOT_ALLOWED작업 세션에 sudo scope가 포함되어 있지 않습니다.세션을 만들 때 sudo scope를 요청하세요.

명령이 서버로 전달되기 전에 거부되는 것은 다른 종류의 실패입니다. API가 api_token_acl_not_allowed로 응답하고 서버에는 아무것도 도달하지 않습니다. 명령줄에 맞는 허용된 명령 규칙이 없다는 뜻이므로 실행하는 그대로 규칙을 작성하세요로 돌아가세요.

권한 상승을 쓸 수 없을 때

배포에서 토큰의 권한 상승이 막혀 있거나 명령이 Critical로 평가된다면 세 가지 방법이 있습니다.

  • sudo가 필요 없게 만드세요. 토큰이 실행되는 계정에 관리 대상을 직접 다룰 권한을 주는 방법입니다. 서비스용 systemd user unit을 쓰거나, 해당 파일을 소유한 그룹에 계정을 넣습니다. 권한 상승 자체가 없으므로 승인할 것도 없습니다. 가장 좁은 방법이며 먼저 시도할 만합니다.
  • 작업 세션 안에서 실행하세요. sudo scope가 포함된 작업 세션은 승인과 감사 기록을 그대로 유지합니다. 대신 사람이 세션을 요청해야 하므로 배포가 완전한 무인 방식은 아니게 됩니다.
  • 호스트의 sudoers 파일에서 직접 허용하세요. 작업은 무인으로 계속 돌지만, 그 호스트의 권한 상승은 Alpacon 밖에서 결정됩니다. 해당 명령들은 Sudo에 남지 않고 어떤 정책이나 승인도 적용되지 않습니다. 최후의 수단으로만 쓰고, Alpacon의 권한 접근 통제에서 의도적으로 제외한 호스트에만 적용하세요.

관련 문서

최종 수정: