[Python] AAA 중 Authorization 관련 모듈 - miracle-acl Develop Tip

보안 부분에서 나온 이야기 이기는 하지만,

인증(Authentication) 관련해서는 사용자가 로그인을 해야하고 로그아웃을 하기 전까지
인증이 필요한 함수를 호출하면 안되도록 해야하는 등의 해당 사용자가 그 사용자가 맞는가를 검증하는 부분입니다.

지난번에 살펴본 [Python] Flask-Login 을 이용한 API 함수 인증 구현 예제 라는 것이 바로 이 인증에 관련된 것이라 보시면 됩니다.

그런데 오늘은 권한검증 Authorization 이라는 것을 살펴보도록 하겠습니다.

우선 권한검증을 리눅스에서 살펴볼 수 있는 것은 바로 파일의 권한이라 하겠습니다.

파일이던 디렉터리던 간에 리눅스에서 ls -l 명령으로 확인해 보면,

-rw-r--r--  1 mcchae  staff   3.4K Sep  5 18:28 acl_test.py

와 같이 보입니다.

사용자는 mcchae 이고 staff 그룹인데 권한은
사용자는 (Read/Write), Group/Others는 (Read) 권한을 가진다는 것을 나타냅니다.

이를 좀 더 개념적으로 살펴보면 권한 검증을 위해서는 다음과 같은 세 단계가 필요하다는 것을 알 수 있습니다.

역할 : 자원 : 권한

이곳에 사용자라는 개념은 아직 없습니다. 대신 사용자는 어떤 역할을 하도록 지정되어 있다고 생각합니다.
역할은 어떤 자원을 접근할 수 있는 주체라고 생각하면 됩니다. 간단하게는 "수퍼유저:관리자:운영자:사용자:손님" 등으로 나누는 식의 역할을 나눌 수가 있습니다. (위의 리눅스에서는 개별 사용자 및 그룹 등이 모두 역할 이라 보면 됩니다)

이제 자원이라는 것은 우리가 생각할 수 있는 권한을 가질 수 있는 대상입니다. 위의 리눅스의 예에서는 해당 파일이나 디렉터리가 바로 이런 권한 검증을 위한 대상, 즉 자원이 되겠네요.

이제 권한이라는 것은 어떤 역할이 어떤 자원을 어떤 권한을 가지고 이용할 수 있는 가를 나타내는 것입니다. 이런 행동을 보통 GRANT(권한 허용) 라는 단어로 표현합니다. 역시 위의 리눅스 예에서 Read/Write/Execute 등이 이런 권한에 해당되겠습니다.

이런 종류의 권한을 예전에도 유사하게 만들어 사용하고는 했는데, 좀 더 찾아보니

miracle-acl 이라는 것이 있었습니다.

0.0.4 버전이라 너무 낮은 거 아닌가 걱정을 했는데 소스를 보더라도 너무 쉬워 그렇게 특별한 것은 없습니다.
위에 해당 내용을 살펴보면, nodejs 모듈 중 miracle 이라는 것에서 영감을 받았다고 하는군요.

역시 문제를 해결하려는 프로그래머는 세상에 수없이 많고 그것에 대한 접근 방법은 다들 대동소이하다고 할 수 있겠네요.

그래서 파이썬에서 테스트를 해 보았습니다.

파이썬 3.6.2에서 작업을 했습니다.
pyenv로 virtualenv 환경을 3.6.2로 만들었구요,

$ pip install miracle-acl

과 같이 설치했습니다.

테스트 소스 에 올려 놓은 것 처럼 ,


$ cat acl_test.py
#!/usr/bin/env python
# coding=utf8

###############################################################################
from miracle.acl import Acl
from pprint import pformat


###############################################################################
def acl_test():
    # =========================================================================
    acl = Acl()
    # =========================================================================
    gr = {
        'root': {
            'api_rest': {'read', 'write', 'create', 'delete'},
            'page_root': {'read', 'write', 'create', 'delete'},
            'page_user': {'read', 'write', 'create', 'delete'},
            'page_guest': {'read', 'write', 'create', 'delete'},
        },
        'users': {
            'api_rest': {'read', 'write', 'create', 'delete'},
            'page_root': {'read'},
            'page_user': {'read', 'write', 'create', 'delete'},
            'page_guest': {'read', 'write', 'create', 'delete'},
        },
        'guests': {
            'page_user': {'read'},
            'page_guest': {'read', 'write', 'create', 'delete'},
        }
    }
    acl.grants(gr)
    # =========================================================================
    print('Roles=%s' % acl.get_roles())
    # =========================================================================
    print('Resources=%s' % acl.get_resources())
    # =========================================================================
    # 해당되는 role:resource:read 가 가능한가 조사 : 없는 역할,리소스 등은 모두 False
    check_arg = ('no_role', 'no_resource', 'read')
    print('check for %s = %s' % (check_arg, acl.check(*check_arg)))
    # 해당되는 role:resource:read 가 가능한가 조사: 가능한 역할,리소스의 권한체크
    check_arg = ('root', 'page_user', 'read')
    print('check for %s = %s' % (check_arg, acl.check(*check_arg)))
    # 해당되는 role:resource:read 가 가능한가 조사: 가능한 역할,리소스의 권한체크
    check_arg = ('users', 'page_root', 'read')
    print('check for %s = %s' % (check_arg, acl.check(*check_arg)))
    # 해당되는 role:resource:read 가 가능한가 조사: 불가능한 역할,리소스의 권한체크
    check_arg = ('users', 'page_root', 'write')
    print('check for %s = %s' % (check_arg, acl.check(*check_arg)))
    # =========================================================================
    # 현재 상태 구하기: json 결과
    save = acl.__getstate__()
    print('save=%s' % pformat(save))
    # =========================================================================
    # 특정 역할:자원:권한 추가
    add_gr = {
        'operators': {
            'page_user': {'read', 'write', 'create', 'delete'},
            'page_guest': {'read', 'write', 'create', 'delete'},
        }
    }
    acl.grants(add_gr)
    print('after added=%s' % pformat(acl.__getstate__()))
    # =========================================================================
    # 특정 역할 삭제
    acl.revoke_all('users')
    print('after deleted=%s' % pformat(acl.__getstate__()))
    # =========================================================================
    acl = Acl()  # new (instead of delete all with traversing)
    acl.__setstate__(save)
    print('after restored=%s' % pformat(acl.__getstate__()))


###############################################################################
if __name__ == '__main__':
    acl_test()

JSON으로 위의 역할:자원:권한 을 지정(GRANT)하고 권한검증 (check)을 하는 것입니다.
위의 것을 Flask에 반영하여 특정 API 또는 FrontEnd의 화면 등에 대한 접근 권한 검증을
쉽게 할 수 있을 것입니다.


어느분께는 도움이 되시기를...


덧글

댓글 입력 영역

구글애드텍스트