![특정 사용자에게 폴더 및 해당 내용에 대한 읽기 권한이 있는지 재귀적으로 확인하는 방법은 무엇입니까?](https://linux55.com/image/67148/%ED%8A%B9%EC%A0%95%20%EC%82%AC%EC%9A%A9%EC%9E%90%EC%97%90%EA%B2%8C%20%ED%8F%B4%EB%8D%94%20%EB%B0%8F%20%ED%95%B4%EB%8B%B9%20%EB%82%B4%EC%9A%A9%EC%97%90%20%EB%8C%80%ED%95%9C%20%EC%9D%BD%EA%B8%B0%20%EA%B6%8C%ED%95%9C%EC%9D%B4%20%EC%9E%88%EB%8A%94%EC%A7%80%20%EC%9E%AC%EA%B7%80%EC%A0%81%EC%9C%BC%EB%A1%9C%20%ED%99%95%EC%9D%B8%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
사용자와 디렉터리를 스크립트에 전달하고 사용자가 읽기 권한을 가지고 있는 해당 디렉터리의 폴더/파일 목록을 표시하도록 해야 합니다. MS에는 이를 수행할 수 있는 Windows용 AccessChk라는 도구가 있는데, Unix 측에도 유사한 도구가 있습니까? 특정 폴더나 파일에 대해 이 작업을 수행할 수 있는 일부 코드를 찾았지만 디렉터리를 탐색하려면 이 코드가 필요합니다.
답변1
긴 이야기 짧게
find "$dir" ! -type l -print0 |
sudo -u "$user" perl -Mfiletest=access -l -0ne 'print if -r'
시스템 사용자에게 읽기 권한이 있는지 물어봐야 합니다. 신뢰할 수 있는 유일한 방법은 유효 uid, 유효 gid 및 보충 gid를 사용자의 유효 uid, 유효 gid 및 보충 gid로 전환하고 시스템 access(R_OK)
호출을 사용하는 것입니다(일부 시스템/구성에는 일부 제한이 있음에도 불구하고).
더 긴 이야기
$user가 읽기 권한을 가지려면 무엇이 필요한지 생각해 봅시다 /foo/file.txt
(둘 중 하나도 심볼릭 링크가 아니라고 가정 /foo
) /foo/file.txt
.
그는 다음이 필요합니다:
- 찾다액세스
/
(필요 없음읽다) - 찾다액세스
/foo
(필요 없음읽다) - 읽다입력하다
/foo/file.txt
사용자에게 또는 검색 권한이 없어도 읽을 수 있다고 되어 있기 file.txt
때문에 단순히 권한을 확인하는 접근 방식은 작동하지 않는다는 것을 이미 알 수 있습니다 .file.txt
/
/foo
유사한 방법:
sudo -u "$user" find / -readable
또한 사용자가 읽을 수 있음에도 불구하고 사용자가 읽기 권한이 없는(내용을 나열할 수 없기 때문에 find
실행 중 ) 디렉토리의 파일을 보고하지 않기 때문에 작동하지 않습니다 .$user
ACL이나 기타 보안 조치(의류, SELinux...)를 잊어버리고 기존 권한과 소유권 속성에만 집중하여 특정(검색 또는 읽기) 권한을 얻는다면 이는 이미 상당히 복잡하고 사용하기 어렵습니다 find
.
다음을 수행해야 합니다.
- 파일이 본인 소유인 경우 소유자의 권한(또는 uid 0)이 필요합니다.
- 파일이 귀하에게 속하지 않지만 그룹에 속해 있는 경우 그룹의 권한이 필요합니다(또는 uid 0이 있어야 함).
- 귀하 또는 귀하의 그룹에 속하지 않는 경우다른권한이 적용됩니다(uid가 0이 아닌 경우).
구문 측면 에서 find
예를 들어 uid 1, gid 1 및 2를 사용하는 사용자는 다음과 같습니다.
find / -type d \
\( \
-user 1 \( -perm -u=x -o -prune \) -o \
\( -group 1 -o -group 2 \) \( -perm -g=x -o -prune \) -o \
-perm -o=x -o -prune \
\) ! -type d -o -type l -o \
-user 1 \( ! -perm -u=r -o -print \) -o \
\( -group 1 -o -group 2 \) \( ! -perm -g=r -o -print \) -o \
! -perm -o=r -o -print
저것치다사용자에게 검색 권한이 없는 디렉터리 및 기타 유형의 파일에 대한 읽기 액세스 권한을 확인합니다(관련이 없는 심볼릭 링크 제외).
또는 사용자 데이터베이스에서 검색된 하나 $user
의 그룹 멤버십 에 대해 다음을 수행합니다.
groups=$(id -G "$user" | sed 's/ / -o -group /g'); IFS=" "
find / -type d \
\( \
-user "$user" \( -perm -u=x -o -prune \) -o \
\( -group $groups \) \( -perm -g=x -o -prune \) -o \
-perm -o=x -o -prune \
\) ! -type d -o -type l -o \
-user "$user" \( ! -perm -u=r -o -print \) -o \
\( -group $groups \) \( ! -perm -g=r -o -print \) -o \
! -perm -o=r -o -print
가장 좋은 방법은 루트로 트리를 내려가고 사용자로 각 파일의 권한을 확인하는 것입니다.
find / ! -type l -exec sudo -u "$user" sh -c '
for file do
[ -r "$file" ] && printf "%s\n" "$file"
done' sh {} +
또는 다음을 사용하여 perl
:
find / ! -type l -print0 |
sudo -u "$user" perl -Mfiletest=access -l -0ne 'print if -r'
또는 다음을 사용하여 zsh
:
files=(/**/*(D^@))
USERNAME=$user
for f ($files) {
[ -r $f ] && print -r -- $f
}
이러한 솔루션은 access(2)
시스템 호출에 의존합니다. 즉, 시스템이 액세스 권한을 확인하는 데 사용하는 알고리즘을 복제하는 대신, 읽기 위해 파일을 열려고 할 때 사용하는 것과 동일한 알고리즘(권한, ACL 등을 고려)을 사용하여 파일을 확인하도록 시스템에 요청합니다. , 그렇습니다. 신뢰할 수 있는 솔루션에 가장 가깝습니다.
이제 이러한 모든 솔루션은 사용자가 읽기 위해 열 수 있는 파일 경로를 식별하려고 시도합니다. 이 경로는 사용자가 콘텐츠를 읽을 수 있는 경로와 다릅니다. 이 보다 일반적인 질문에 답하기 위해 고려해야 할 몇 가지 사항은 다음과 같습니다.
- $user는 $user에 대한 읽기 액세스 권한이 없을 수 있지만
/a/b/file
,file
$user에 대한 검색 액세스 권한이 있고 시스템에 대한 셸 액세스 권한이 있는 경우 $user의 권한을 변경 하고 자신에게 액세스 권한을 부여/a/b
할 수 있습니다.file
. /a/b
검색 권한이 있지만 검색 권한이 없는 경우에도 마찬가지입니다.- $user는 또는 에 대한 검색 액세스 권한이
/a/b/file
없기 때문에 액세스 권한이 없을 수 있지만 파일에 하드 링크가 있을 수 있습니다 . 이 경우 예를 들어 해당 경로를 통해 내용을 열어 내용을 읽을 수 있습니다./a
/a/b
/b/c/file
/a/b/file
/b/c/file
- 같은 것번들 설치. 그 사람 은 검색 권한이 없을 수도
/a
있지만/a/b
번들 설치, 다른 경로를 통해 읽을 수 있도록 열 수/c
있습니다 .file
/c/file
$user
읽을 수 있는 경로를 찾으십시오. 1번이나 2번을 해결하기 위해 더 이상 시스템 호출에 의존할 수 없습니다 access(2)
. find -perm
디렉토리에 대한 검색 액세스 권한을 가정하거나 소유자가 되자마자 파일에 대한 읽기 액세스 권한을 갖도록 접근 방식을 조정할 수 있습니다 .
groups=$(id -G "$user" | sed 's/ / -o -group /g'); IFS=" "
find / -type d \
\( \
-user "$user" -o \
\( -group $groups \) \( -perm -g=x -o -prune \) -o \
-perm -o=x -o -prune \
\) ! -type d -o -type l -o \
-user "$user" -print -o \
\( -group $groups \) \( ! -perm -g=r -o -print \) -o \
! -perm -o=r -o -print
장치 및 inode 번호 또는 $user가 읽기 권한을 갖고 있는 모든 파일을 기록하고 해당 dev+inode 번호가 포함된 모든 파일 경로를 보고하여 3번과 4번 문제를 해결할 수 있습니다. 이번에는 보다 안정적인 access(2)
기반 접근 방식을 사용할 수 있습니다.
그것은 다음과 같습니다:
find / ! -type l -print0 |
sudo -u "$user" perl -Mfiletest=access -0lne 'print 0+-r,$_' |
perl -l -0ne '
($w,$p) = /(.)(.*)/;
($dev,$ino) = stat$p or next;
$writable{"$dev,$ino"} = 1 if $w;
push @{$p{"$dev,$ino"}}, $p;
END {
for $i (keys %writable) {
for $p (@{$p{$i}}) {
print $p;
}
}
}'
두 솔루션을 다음으로 병합합니다.
{ solution1; solution2
} | perl -l -0ne 'print unless $seen{$_}++'
지금까지 모든 내용을 읽었다면 최소한 그 일부는 권한과 소유권만 다루고 읽기 액세스를 부여하거나 제한할 수 있는 다른 기능(ACL, 기타 보안 기능...)은 다루지 않는다는 점을 분명히 해야 합니다. 여러 단계로 처리하므로 스크립트가 실행되는 동안 파일/디렉터리가 생성/삭제/이름이 바뀌거나 해당 권한/소유권이 수정되면 일부 정보가 손실될 수 있습니다. 예를 들어 수백만 개의 파일이 있는 바쁜 파일 서버에서는 잘못된 것입니다.
이식성 참고 사항
이 코드는 모두 다음을 제외하고 표준(POSIX, t
비트용 Unix)입니다.
-print0
GNU 확장이며 이제 여러 다른 구현에서도 지원됩니다.find
지원이 부족한 구현 의 경우-exec printf '%s\0' {} +
대신 사용하고-exec sh -c 'exec find "$@" -print0' sh {} +
로 바꿀 수 있습니다-exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +
.perl
POSIX 특정 명령은 아니지만 널리 사용 가능합니다. 당신은perl-5.6.0
이상이 필요합니다-Mfiletest=access
.zsh
POSIX 지정 명령이 아닙니다. 위 코드는zsh
zsh-3(1995) 이상에서 작동합니다.sudo
POSIX 지정 명령이 아닙니다. 코드는 시스템 구성에서perl
특정 사용자로 실행을 허용하는 한 모든 버전에서 작동해야 합니다.
답변2
이는 해결책을 얻는 쉬운 방법입니다. "testuser"를 자신의 사용자로 바꾸십시오. find 사용법을 알고 있고 "." 인수를 대체하여 관련 디렉토리를 찾을 수 있다고 가정합니다.
x=테스트 사용자 찾기; -type f |xargs ls -la | grep $x |
test1-3.txt라는 이름의 일부 파일을 사용하여 세 개의 디렉터리 심층 구조(dir1, dir2, dir3)를 만들었습니다. 나는 사용자나 그룹을 일부 파일에 testuser로 임의로 할당합니다.
[root@myserver tmp]# x=testuser;찾기. -type f |xargs ls -la | grep $x 쿼리 awk '{print$9}'
./dir1/dir2/dir3/test2.txt
./dir1/test2.txt
./dir1/test3.txt
핵심은 "ls"의 재귀 옵션입니다. 다음은 내 테스트의 구조에 대한 예입니다.
[root@det1svn01n tmp]# ls -laR dir1
카탈로그 1:
총 12개
drwxr-xr-x 3 루트 루트 4096 6월 17일 14:55.
drwxrwxrwt 4 gengen4096 6월 17일 14:54 ..
drwxr-xr-x 3 testuser testuser 4096 6월 17일 14:55 dir2
-rw-r--r-- 1 루트 루트 0 6월 17일 14:55 test1.txt
-rw-r--r-- 1 루트 testuser 0 6월 17일, 14:55 test2.txt
-rw-r--r-- 1 testuser testuser 0 6월 17일 14:55 test3.txt
디렉터리 1/디렉터리 2:
총 12개
drwxr-xr-x 3 testuser testuser 4096 6월 17일 14:55.
drwxr-xr-x 3 root4096 6월 17일 14:55 ..
drwxr-xr-x 2 루트 root4096 6월 17일 14:55 dir3
-rw-r--r-- 1 루트 루트 0 6월 17일 14:55 test1.txt
-rw-r--r-- 1 루트 루트 0 6월 17일 14:55 test2.txt
-rw-r--r-- 1 루트 루트 0 6월 17일 14:55 test3.txt
디렉터리 1/디렉터리 2/디렉터리 3:
총 8개
drwxr-xr-x 2 root4096 6월 17일 14:55.
drwxr-xr-x 3 testuser testuser 4096 6월 17일 14:55 ..
-rw-r--r-- 1 루트 루트 0 6월 17일 14:55 test1.txt
-rw-r--r-- 1 루트 루트 0 6월 17일 14:55 test2.txt
-rw-r--r-- 1 루트 루트 0 6월 17일 14:55 test3.txt