특정 사용자에게 폴더 및 해당 내용에 대한 읽기 권한이 있는지 재귀적으로 확인하는 방법은 무엇입니까?

특정 사용자에게 폴더 및 해당 내용에 대한 읽기 권한이 있는지 재귀적으로 확인하는 방법은 무엇입니까?

사용자와 디렉터리를 스크립트에 전달하고 사용자가 읽기 권한을 가지고 있는 해당 디렉터리의 폴더/파일 목록을 표시하도록 해야 합니다. 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.

그는 다음이 필요합니다:

  1. 찾다액세스 /(필요 없음읽다)
  2. 찾다액세스 /foo(필요 없음읽다)
  3. 읽다입력하다/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 등을 고려)을 사용하여 파일을 확인하도록 시스템에 요청합니다. , 그렇습니다. 신뢰할 수 있는 솔루션에 가장 가깝습니다.

이제 이러한 모든 솔루션은 사용자가 읽기 위해 열 수 있는 파일 경로를 식별하려고 시도합니다. 이 경로는 사용자가 콘텐츠를 읽을 수 있는 경로와 다릅니다. 이 보다 일반적인 질문에 답하기 위해 고려해야 할 몇 가지 사항은 다음과 같습니다.

  1. $user는 $user에 대한 읽기 액세스 권한이 없을 수 있지만 /a/b/file, file$user에 대한 검색 액세스 권한이 있고 시스템에 대한 셸 액세스 권한이 있는 경우 $user의 권한을 변경 하고 자신에게 액세스 권한을 부여 /a/b할 수 있습니다. file.
  2. /a/b검색 권한이 있지만 검색 권한이 없는 경우에도 마찬가지입니다.
  3. $user는 또는 에 대한 검색 액세스 권한이 /a/b/file없기 때문에 액세스 권한이 없을 수 있지만 파일에 하드 링크가 있을 수 있습니다 . 이 경우 예를 들어 해당 경로를 통해 내용을 열어 내용을 읽을 수 있습니다./a/a/b/b/c/file/a/b/file/b/c/file
  4. 같은 것번들 설치. 그 사람 은 검색 권한이 없을 수도 /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)입니다.

  • -print0GNU 확장이며 이제 여러 다른 구현에서도 지원됩니다. find지원이 부족한 구현 의 경우 -exec printf '%s\0' {} +대신 사용하고 -exec sh -c 'exec find "$@" -print0' sh {} +로 바꿀 수 있습니다 -exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +.
  • perlPOSIX 특정 명령은 아니지만 널리 사용 가능합니다. 당신은 perl-5.6.0이상이 필요합니다 -Mfiletest=access.
  • zshPOSIX 지정 명령이 아닙니다. 위 코드는 zshzsh-3(1995) 이상에서 작동합니다.
  • sudoPOSIX 지정 명령이 아닙니다. 코드는 시스템 구성에서 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

관련 정보