cronjob에서 실행되는 명령(예: logrotate)에는 selinux 정책이 작동하지만 명령줄에서 직접 실행되는 명령에는 작동하지 않는 이유는 무엇입니까?

cronjob에서 실행되는 명령(예: logrotate)에는 selinux 정책이 작동하지만 명령줄에서 직접 실행되는 명령에는 작동하지 않는 이유는 무엇입니까?

cronjob에서 실행되는 명령(예: logrotate)에는 selinux 정책이 작동하지만 명령줄에서 직접 실행되는 명령에는 작동하지 않는 이유는 무엇입니까?

명령줄에서 수동으로 logrotate를 실행하면 정상적으로 작동합니다. 그러나 cronjob에서 실행하면 audit.log에 selinux가 www 등에 대한 액세스를 차단한다는 오류가 표시됩니다.

왜 그런 겁니까? 테스트하기 위해 cronjob에서 실행되는 것을 어떻게 시뮬레이션할 수 있나요?

답변1

cron를 실행할 때 logrotateSELinux는 이를 logrotate_t "유형"으로 제한합니다. 이 "유형"은 다른 파일 유형을 수정하는 것이 제한됩니다("이스케이프 제한"이라고도 함).

언제logrotate를 실행하면 "무제한" 유형으로 시작할 가능성이 높습니다. 즉, logrotate프로세스가 파일을 수정할 수 있다는 의미입니다. 프로세스를 다시 시작하거나 신호를 보낼 수도 있습니다 logrotate(예: postrotate). 이 활동은 SELinux에 의해 제한될 수도 있습니다.

내 제안은 SELinux에게 다음과 같이 logrotate_t 유형이 제한을 벗어날 수 있도록 허용("허용")하도록 지시하는 것입니다.

semanage permissive -a logrotate_t

이렇게 하는 것은 중간 정도의 가벼운 해결책입니다.SELinux 끄기그리고 필요한 제한 탈출을 정확히 허용하도록 정책을 미세 조정합니다(아마도 사용자 정의 태그 사용). 이 변경 사항을 되돌리려면 를 사용하십시오 semanage permissive -d logrotate_t.

cron 실행 프로세스를 시뮬레이션하는 가장 좋은 방법은 작업을 cron에 넣는 것입니다. 그리고 나도 알아runcon, 비록 나는 그것을 사용하는데 성공하지 못했습니다.

답변2

특정 질문에 관한 @JeffSchaller의 좋은 답변에 추가하면 됩니다.

테스트하기 위해 cronjob에서 실행되는 것을 어떻게 시뮬레이션할 수 있나요?

cronjob에서 테스트 명령을 실행하지 않고도 작업 대안을 공유할 수 있습니다.

첫째, 언급할 가치가 있는 미묘한 세부 사항입니다.

전통적인 비 SELinux 환경에서 루트(유효 UID = 0)로 작업할 때 일반적으로 해당 UID의 제한 사항을 "얻기" 위해 원하는 다른 UID로 자유롭게 전환할 수 있습니다.

이는 SELinux와 완전히 다른 컨텍스트입니다. 루트(유효 UID = 0)가 되면 일반적으로 "무제한" 컨텍스트에 놓이게 되지만 자동으로 다른 컨텍스트로 자유롭게 전환할 수는 없습니다. 오히려 특정 "변환" 작업을 수행하기 위해 "제한되지 않은" 컨텍스트 권한을 부여하려면 명시적인 SELinux 정책 규칙이 필요합니다. 이러한 규칙을 설치한 후 runcon명령은 해당 컨텍스트에 성공적으로 배치됩니다.

실제로 귀하의 경우에는 다음과 같은 SELinux 정책이 필요할 수 있습니다.

allow unconfined_t crond_t:process transition;

(이것이 데몬이 실행 중인 SELinux 도메인이라고 가정 crond_t)crond

전체 모듈의 컴파일 및 설치 규칙은 다음과 같습니다.

module unconfined-trans-crond 1.0;

require {
        type unconfined_t;
        type crond_t;
        class process transition;
}

allow unconfined_t crond_t:process transition;

모듈을 컴파일하고 설치한 후 runcon 대상 crond_t도메인을 사용할 수 있습니다 unconfined_t. 예를 들어:

# id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# runcon $(ps -q $(pgrep crond) -o context --no-header) sh
# id
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:crond_t:s0
#

또한 이 작업을 수행하려면 UID 0이 필요하지 않으며 runcon현재 SELinux 컨텍스트에서 대상 SELinux 컨텍스트로 전환을 허용하는 올바른 정책 규칙이 "단지" 필요합니다.

실제로 데몬(예: crond)을 테스트하기 위해 일반적으로 루트로 실행하는 전체 명령은 다음과 같습니다.

runuser $(ps -q $(pgrep crond) -o user --no-header) -c 'runcon $(ps -q $(pgrep crond) -o context --no-header) /bin/bash'

crond사용자로 실행되는 쉘과 해당 SELinux 컨텍스트를 제공합니다.

테스트를 완료한 후 정책을 실행 취소하려면 사용자 지정 모듈을 삭제하면 됩니다.

물론 이는 다양한 네임스페이스 보기, 리소스 제한(ulimits), cgroups 또는 Linux 기능과 같은 가능한 다른 제한 사항을 고려하지 않습니다. PAM 구성이 runuser다시 생성된 방식과 어느 정도 일치 하지 않는 한 이러한 추가 제한 사항을 다시 생성하려면 추가 명령을 순서대로 실행해야 합니다 .

화타이

답변3

@Jeff_Schaller와 @LL3의 답변에서 영감을 받아 이 프로세스에 적합한 sepolicy 모듈을 찾는 방법은 다음과 같습니다.

:; sudo semanage permissive -a logrotate_t
# turn off selinux for logrotate temporarily to allow the logrotate command to go through, while still logging the denied messages in audit.log

:; sudo runcon -u system_u -r system_r -t logrotate_t logrotate -f /etc/logrotate.conf
:; sudo semanage permissive -d logrotate_t # re-enable selinux

:; sudo grep denied /var/log/audit/audit.log | audit2allow -M logrotate
# create a selinux policy based on the denied messages

:; sudo semodule -i logrotate.pp

내용은 logrotate.te이렇게 끝납니다

module logrotate 1.0;

require {
        type initrc_exec_t;
        type default_t;
        type policykit_t;
        type logrotate_t;
        class dbus send_msg;
        class file { create getattr ioctl open read setattr unlink write };
        class dir { add_name read remove_name write };
        class service reload;
}

#============= logrotate_t ==============
allow logrotate_t default_t:dir { add_name read remove_name write };

#!!!! WARNING: 'default_t' is a base type.
allow logrotate_t default_t:file { create getattr ioctl open read setattr unlink write };
allow logrotate_t initrc_exec_t:service reload;
allow logrotate_t policykit_t:dbus send_msg;

답변4

나는 SElinux에 대해 깊은 이해가 없으며 다른 답변과 같은지 확실하지 않습니다. 내가하는 방법은 다음과 같습니다. 디렉토리 내부. semanage fcontext -a -t 'myCronTab' logrotate_exec_t이렇게 하면 crontab과 cronjob이 logrotate동일한 컨텍스트 에 놓이게 되므로 마치 명령줄에서 실행되는 것과 같아야 합니다.

관련 정보