토큰 명령어 매칭
토큰이 명령어를 허용하는지 확인할 때 이 규칙을 사용하세요. 자동화 작업에 앞서 서비스 토큰의 허용 명령어를 설정하세요.
명령 규칙은 어떻게 매칭되나요
허용 명령 규칙은 토큰별로 설정합니다. 기존 개인 API 토큰과 서비스 토큰을 참고하세요. 제출한 명령줄을 허용하는 규칙과 서버의 권한 상승 허용 여부는 각각 확인합니다. sudo로 시작하는 명령에는 규칙에도 sudo가 있어야 합니다. 두 권한은 설정 위치가 다르고 적용 방식도 반대여서 자동 배포가 여기서 멈추는 경우가 가장 많습니다.
- 규칙을 제출한 명령줄 전체와 처음부터 끝까지 비교합니다. 일부만 일치하면 허용하지 않습니다.
- 와일드카드는
*만 사용할 수 있습니다. 규칙 맨 끝에 단독으로 오는*는 나머지 인수 전체와 일치하고,*하나만 있는 규칙도 아래의 첫 단어 제한을 따릅니다. 그 밖의*는 단어 하나 안에서만 일치하며 공백과$,`,*,?,[,{와는 일치하지 않습니다. 따라서deploy-*는deploy-web은 허용하지만deploy-web --force는 허용하지 않습니다.*를 따옴표로 감싸거나 이스케이프한 규칙은 어떤 명령줄과도 일치하지 않습니다. 규칙의 첫 단어에*가 있으면 환경 변수 대입(NAME=value …)이나 셸 접두어(time,!,if,then,else,elif,while,until,do,{)로 시작하는 명령줄과는 일치하지 않습니다. 첫 단어가*하나뿐이어도 마찬가지입니다. 이런 명령어를 허용하려면 규칙에 접두어를 그대로 적어야 합니다. - 단어 안에서 고정 문자열 뒤에 오는
*는 상위 디렉터리 구간(..뒤에/,:,,, 공백이 오거나 단어가 끝나는 경우)과 일치하지 않습니다. 따라서rm -rf /tmp/build-*규칙은rm -rf /tmp/build-x/sub와 일치하지만rm -rf /tmp/build-x/../../etc와는 일치하지 않습니다. 단어 맨 앞의*는cp * /dst처럼 상위 디렉터리 구간과도 일치하며,git log v1..*처럼 규칙에 직접 적힌..는 문자 그대로 비교합니다. - 명령줄에서
&&,||,|,;,&, 줄바꿈으로 여러 명령어를 연결하면 각 부분을 따로 비교하며, 모든 부분이 규칙 중 하나에 일치해야 합니다. - 리디렉션이 있는 명령줄은 규칙과 관계없이 거부합니다.
*하나뿐인 규칙도 마찬가지입니다.>,>>,<,>|뿐 아니라2>&1,2>/dev/null,<<같은 형태도 해당합니다. 규칙으로는 명령어가 어떤 파일을 읽거나 쓸 수 있는지 정할 수 없기 때문입니다. 제출하는 명령줄에서 리디렉션을 빼거나, 서버의 스크립트 안으로 옮기고 그 스크립트 이름을 규칙에 등록해야 합니다. 프로세스 치환(<(...))은 리디렉션이 아니며 다른 명령과 똑같이 검사합니다. - 단어 맨 앞의
#부터는 셸과 같이 주석으로 처리합니다. 그 줄의 나머지는 무시되며 규칙과 일치하는 데 쓰이지 않고, 다음 줄은 다시 비교합니다. 단,$(...)나 서브셸(...)안의#는 주석으로 보지 않고 줄 전체를 거부합니다. - 셸마다 따옴표를 다르게 해석하는 명령줄은 거부합니다. 예를 들어
"${x:-...}"안의 작은따옴표가 해당합니다. - 비교 전에 따옴표를 제거하고 연속된 공백을 하나로 줄입니다. 따라서
echo "hello world"는echo hello world로,echo hello(공백 두 개)는echo hello로 비교합니다. - 일치하는 규칙이 없으면 서버에서는 아무 명령어도 실행되지 않습니다. Alpacon Cloud에서는 명령이 접수된 뒤
실행 전에
command_acl_denied로 거부되고, 자체 호스팅 배포에서는 요청이api_token_acl_not_allowed로 거부됩니다. 거부 메시지를 참고하세요.
끝의 와일드카드는 인자를 요구합니다
*로 끝나는 규칙은 인수를 하나 이상 요구합니다. 와일드카드 앞의 공백도 규칙에 포함되기 때문입니다.
| 규칙 | 허용하는 명령어 | 허용하지 않는 명령어 |
|---|---|---|
docker | docker | docker ps |
docker * | docker ps, docker compose up -d | docker(인수 없음) |
systemctl status * | systemctl status nginx | systemctl restart nginx |
인수가 없는 명령어와 인수가 있는 명령어를 모두 허용하려면 docker와 docker * 규칙을 각각
추가하세요.
규칙의 사용자와 그룹
각 규칙은 명령어를 실행할 수 있는 시스템 사용자와 그룹도 지정합니다.
| 토큰 유형 | 사용자 이름을 비운 경우 | 사용자 이름이 *인 경우 | 사용자 이름이 deploy인 경우 |
|---|---|---|---|
| API 액세스 토큰 | 토큰 소유자만 허용 | 모든 사용자 허용 | deploy만 허용 |
| 서비스 토큰 | 모든 사용자 허용 | 모든 사용자 허용 | deploy만 허용 |
서비스 토큰은 개인이 아닌 애플리케이션에 속하므로 기본값으로 사용할 소유자가 없습니다. 서비스 토큰 규칙에서 사용자 이름을 비워 두면 모든 시스템 사용자가 허용됩니다. 한 계정으로 제한하려면 사용자 이름을 명시하세요.
명령 규칙과 sudo 정책은 정반대입니다
Alpacon에서는 명령 패턴을 sudo 정책에도 씁니다. 이 정책은 어떤 사용자가 어떤 서버에서 권한을 높일 수 있는지 결정합니다. 두 패턴은 비슷해 보이지만 검사 시점과 비교 대상이 달라, 같은 명령에도 서로 반대되는 패턴을 써야 합니다.
| 허용 명령 규칙 | sudo 정책 | |
|---|---|---|
| 적용 대상 | 토큰 하나 | 선택한 서버의 Alpacon 사용자 |
| 검사 시점 | 명령을 서버로 보내기 전 | 서버가 Alpacon에 권한 상승 승인을 요청할 때 |
| 비교 대상 | sudo를 포함해 입력한 명령줄 | sudo를 제외하고 root 권한으로 실행할 명령 |
sudo systemctl restart nginx의 패턴 | sudo systemctl restart nginx | systemctl restart nginx |
패턴 앞의 sudo | 필요 | 정책 저장 시 거부됨 |
| 일치하지 않을 때 | 명령이 거부되고 아무것도 실행되지 않음 | 권한 상승이 거부되고 sudo가 오류를 내며 종료됨 |
sudo로 시작하는 패턴이 들어 있는 sudo 정책은 저장할 때 sudo_policy_pattern_has_sudo_prefix
오류가 납니다. 의도적으로 그렇게 설계했습니다. 이런 패턴은 어떤 명령에도 일치할 수 없으므로, 몇 주
뒤 이유도 모른 채 거부되는 것보다 입력할 때 오류를 알려주는 편이 낫습니다.
sudo 정책을 만들고 사용하는 방법은 sudo with MFA를 참고하세요.
거부 메시지
권한 상승이 거부되면 터미널에 Alpacon denied this sudo command (CODE).가 표시되고 sudo가 0이
아닌 종료 상태로 끝납니다.
| 코드 | 의미 | 해결 방법 |
|---|---|---|
SUDO_RISK_DENIED | 명령의 위험도가 심각으로 평가되었거나 워크스페이스에서 허용하는 수준을 넘었으며, 승인한 사람이 없음 | 사람이 명령 자체를 승인해야 함. 작업 세션에서 실행하면 보류된 명령에 대한 승인이 해당 명령의 sudo에도 적용됨. 또는 명령을 더 작은 범위로 나누어 실행해야 함 |
SUDO_COMMAND_NOT_AUTHORIZED | 이 배포 환경에서는 sudo 명령어의 실행 주체를 사람으로 확인할 수 없음 | 로그인한 사람이 권한을 받아 명령어를 실행해야 함. 자체 호스팅의 기본 서비스 토큰 sudo 결과임 |
SUDO_NO_WORKSESSION_POLICY | 이 명령과 일치하는 sudo 정책이 없음 | 명령어 패턴이 일치하는 작업 세션에서 실행해야 함. 패턴 추가에는 승인이 필요할 수 있음 |
SUDO_POLICY_MFA_REQUIRED | 일치하는 sudo 정책에 MFA가 필요하지만 비대화형 명령어에서는 완료할 수 없음 | 대화형 터미널에서 MFA를 완료하고 명령어를 실행해야 함 |
WORK_SESSION_SCOPE_NOT_ALLOWED | 작업 세션에 sudo 범위가 포함되지 않음 | 세션을 만들 때 sudo 범위를 요청해야 함 |
토큰의 허용 명령 규칙이 명령을 거부했다면 다른 문제입니다. 이 경우에는 서버에 아무것도 전달되지 않으며, 거부가 드러나는 방식은 배포 환경에 따라 다릅니다.
Alpacon Cloud에서는 API가 명령을 접수한 뒤, 실행 전에 command_acl_denied로 거부합니다. 명령어 기록에서 명령을 열고
거절 이유에서 사유를 확인하세요.
자체 호스팅 배포에서는 명령을 보내기 전에 API가 api_token_acl_not_allowed를 반환합니다.
응답은 원인과 관계없이 같습니다. 거부된 명령은 명령 기록에 남고, 그
거절 사유를 보면 아래 세 원인 중 무엇인지 알 수 있습니다.
Command contains a redirection (>, >>, <); ...: 어떤 규칙으로도 허용할 수 없는 명령줄입니다. 리디렉션을 빼거나 서버의 스크립트 안으로 옮기세요.Command quoting or a comment cannot be read the same way by every shell, ...또는Command contains shell quoting that could obfuscate substitutions.: 이것도 규칙으로 허용할 수 없습니다. 따옴표를 단순하게 바꾸고$'...'와$"..."를 피하거나, 주석을$(...)나(...)밖으로 옮기세요.- 그 밖의 사유는 입력한 명령줄과 일치하는 허용 명령 규칙이 없다는 뜻입니다. 실행하는 명령 그대로 규칙 작성하기를 다시 확인하세요.
같은 api_token_acl_not_allowed 코드라도 서버, 명령어 또는 파일 접근이 거부된 경우일 수 있습니다. 보고된 검사 단계와 명령어 거부 사유를 확인한 뒤 해당 규칙을 수정하세요. 명령어가 거부되었다면 허용 명령어를, 서버나 파일이 거부되었다면 해당 접근 규칙을 확인하세요.