Ubuntu 26.04 강좌 / AppArmor 로그와 프로파일 점검하기

AppArmor는 프로그램별 프로파일로 파일·실행·네트워크 등의 동작을 제한하는 추가 접근 제어입니다. 권한 오류를 조사할 때는 일반 파일 권한과 실제 적용 프로파일·거부 로그를 함께 확인하며, AppArmor 전체 해제를 첫 해결책으로 삼지 않습니다.

일반 권한과 프로파일의 차이

사용자의 UID·그룹·파일 모드가 허용하더라도 AppArmor가 해당 프로그램의 접근을 막을 수 있습니다. 반대로 AppArmor 로그가 없다고 일반 디렉터리 권한·읽기 전용 마운트·서비스 계정 문제까지 정상인 것은 아닙니다. 실제 실패한 경로와 실행 계정을 먼저 기록합니다.

현재 프로파일과 모드 확인하기

sudo aa-status
systemctl status apparmor --no-pager

프로파일의 enforce와 complain은 동작이 다릅니다. enforce는 정책을 적용하고 complain은 학습·조사에 활용되지만 보호 범위를 줄일 수 있습니다. 서비스 상태만으로 모든 프로세스가 제한된다고 판단하지 말고 aa-status의 실제 프로파일과 연결된 프로세스를 봅니다.

Ubuntu 보안 문서는 AppArmor의 정책 적용과 프로파일 모드·권한 범위를 설명합니다.

실패 직후의 로그와 요청 대조하기

sudo journalctl -k -b --since '10 minutes ago' --no-pager | grep 'apparmor="DENIED"'

실패를 한 번 재현한 시각을 기록하고 profile·operation·name·pid·requested_mask·denied_mask를 대조합니다. 로그 예시를 실제 장치의 결과처럼 꾸미지 말고 현재 출력에서 해당 프로그램과 요청이 맞는지 확인합니다. 내부 경로와 사용자 정보가 포함될 수 있으므로 공유할 때 필요한 부분만 남깁니다.

출력이 없으면 현재 부팅·시간 범위·로그 수집 경로와 실제 프로파일을 다시 확인합니다. 명시적인 deny 규칙 등은 기대한 방식으로 로그가 나오지 않을 수 있으므로 로그 부재를 정책 허용의 증거로 보지 않습니다.

거부 기록의 필드를 예시로 읽기

다음 한 줄은 필드 설명을 위해 만든 가상 예시이며 특정 Ubuntu 장치에서 수집한 결과가 아닙니다. profile은 제한된 프로그램 정책, operation은 시도한 동작, name은 대상 경로이고 requested_mask와 denied_mask의 r은 읽기 요청과 거부를 나타냅니다.

apparmor="DENIED" operation="open" profile="/usr/sbin/example-app" name="/srv/example-data/settings.ini" requested_mask="r" denied_mask="r"

실제 조사에서는 실패 시각·프로세스·실행 계정·경로를 로그와 맞춥니다. 예시 경로에 읽기 권한을 추가하라는 처방이 아닙니다. 잘못된 앱 데이터 위치를 원래 지원 위치로 되돌리는 것이 적절할 수도 있으며, 로그에 나온 모든 요청을 허용하지 않습니다.

프로파일과 설정 소유자 찾기

일반 프로파일은 /etc/apparmor.d에서 해당 이름과 실행 경로를 찾습니다. Snap처럼 정책이 생성되는 앱은 생성된 파일을 직접 고치기보다 Snap 인터페이스와 제공자 설정을 확인합니다. 파일 이름을 추정해 새 프로파일을 만들거나 다른 프로그램의 정책을 복사하지 않습니다.

경로 변경이 원인이라면 먼저 앱이 지원하는 데이터 위치로 되돌리는 방법을 검토합니다. 정책 수정이 필요하면 실제 요구 동작·정확한 파일 경로·읽기/쓰기 범위를 정하고 원본과 포함된 local 설정을 백업합니다. 넓은 와일드카드로 전체 디스크를 허용하지 않습니다.

커널 정책을 바꾸지 않고 프로파일 검사하기

일반 프로파일 하나의 실제 파일을 확인하고 아래 프롬프트에 입력합니다. Snap이 자동 생성한 정책은 이 편집 실습 대상에서 제외합니다. -Q는 커널 로드를 건너뛰고 -K는 캐시 사용·기록을 하지 않게 합니다. 검사가 통과해도 앱의 실제 접근 허용·거부 시험이 끝난 것은 아닙니다.

(
set -eu
read -r -p 'Actual ordinary profile path under /etc/apparmor.d/: ' profile
case "$profile" in
    /etc/apparmor.d/*) ;;
    *) printf 'Choose the verified profile source.\n' >&2; exit 1 ;;
esac
sudo test -f "$profile"
sudo apparmor_parser -Q -K "$profile"
)

실제 정책을 좁게 수정해야 하는 경우 원본과 local 포함 파일을 먼저 백업하고 위 검사를 통과한 뒤 sudo apparmor_parser -r 실제프로파일파일로 그 프로파일을 다시 읽힙니다. 실패하면 같은 파일의 백업만 복원해 검사·재적용하고 aa-status와 원래 enforce 상태를 확인합니다. 이 글의 조회 실습만 하려면 reload 명령은 실행하지 않습니다.

AppArmor 5.0 공식 매뉴얼에서 검사·캐시·커널 재적용의 차이를 확인하세요.

좁은 변경과 검증·복원 기준

변경한 프로파일은 공식 도구로 구문을 확인하고 해당 프로파일만 다시 읽게 한 뒤 허용해야 할 동작과 계속 막아야 할 동작을 각각 시험합니다. 진단 도구가 제안한 허용 규칙도 로그의 모든 요청을 무조건 승인하지 말고 필요성을 검토합니다.

실패하면 이번 정책 변경만 복원하고 원래 enforce 상태와 앱 동작을 재확인합니다. 전체 AppArmor 서비스나 사용자 네임스페이스 보호를 끄는 명령으로 결과를 맞추지 않습니다. 완료 기록에는 원인·정책 경로·변경 범위·허용 및 거부 시험·복원 방법을 남깁니다.