ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • NGINX 6: 인증
    DevOps 2023. 3. 19. 02:23
    반응형

     

    엔진엑스는 클라이언트에 대한 요청을 인증함으로써 업스트림 서버에서 인증을 처리하며 발생하는 부하를 줄이고 동시에 인증받지 못한 요청이 애플리케이션 서버까지 도달하는 것을 막을 수 있습니다.

     

    오픈소스 버전은 인증 모듈로 HTTP 기본 인증하위 요청을 통한 인증을 제공하며 엔진엑스 플러스는 JWT 검증 모듈과 표준 오픈 아이디 커넥트 인증을 제공하는 서드파티 인증 사업자들을 엔진엑스로 통합합니다.

     

     

    1. HTTP 기본 인증


    사용자 이름과 비밀번호를 이용한 HTTP 기본 인증을 통해서 애플리케이션과 콘텐츠를 안전하게 보호할 수 있습니다.

     

    다음과 같이 conf.d 디렉터리에 passwd 파일을 생성합니다.

    name1:password1
    name2:password2:comment
    name3:password3
    • 각 행의 첫 번째 필드는 username이고 두 번째 필드는 password입니다.
    • 사용자에 대해 기록해둘 내용이 있으면 세 번째 필드를 사용하고 각 필드는 콜론으로 구분합니다.
    • 엔진엑스는 대표적으로 C언어에서 제공하는 crypt() 함수로 암호화된 비밀번호 형식을 지원을 하는데요, openssl을 통해 사용하는 passwd 명령도 내부적으로는 crypt() 함수를 이용해 구현돼 있기 때문에 다음 명령을 입력해서 비밀번호를 암호화 합니다.
    $ openssl passwd MyPassword1234
    • 명령을 실행하면 암호화된 문자열을 얻으며 엔진엑스의 비밀번호 파일에 그대로 사용할 수 있습니다.

     

    HTTP 기본 인증을 활성화하려면 엔진엑스 설정 파일에서 auth_basic 지시자와 auth_basic_user_file 지시자를 사용합니다.

    location / {	
        auth_basic "Private site";
        auth_basic_user_file conf.d/passwd;
    }
    • auth_basic 지시자는 http, server, location 컨텍스트에서 사용할 수 있고, 문자열로 된 매개변수를 입력하면 인증받지 않은 사용자가 접근할 때 브라우저가 인증 팝업창을 띄우고 지정된 문자열을 보여줍니다.
    • auth_basic_user_file 지시자에는 사용자 이름과 비밀번호가 저장된 파일의 경로를 지정합니다.

     

    설정에 문제가 없는지 확인하려면 curl 명령을 사용하며 --u나 --user 옵션을 사용해 사용자 이름과 비밀번호를 입력하고 Authroization 헤더를 만듭니다.

    $ curl --user myuser:MyPassword1234 https://localhost
    • 인증에 성공하지 못한 사용자에게는 '401 Unauthorized' 응답과 함께 WWW-Authenticate 헤더를 회신합니다.
    • 헤더 값은 Basic realm="auth_basic 지시자에 지정한 메시지"가 됩니다.
    • 사용자 인증 요청은 username과 password를 콜론으로 연결한 문자열 형태이고 엔진엑스로 전달되기 전에 base64로 인코딩되고Authorization 요청 헤더값ㅇ로 지정됩니다.
    • 서버는 헤더를 디코딩하고 auth_basic_user_file 지시자가 지정한 파일을 이용해 인증을 진행합니다.

     

     

    2. 인증을 위한 하위 요청


    요청된 리소스에 대해 응답하기 전에 http_auth_request_module을 사용해 서드파티 인증 서비스로 요청을 보내고 요청자의 ID를 확인합니다.

    location /private/ {	
        auth_request /auth;
        auth_request_set $auth_status $upstream_status;
    }
    
    location = /auth {	
        internal;
        proxy_pass 		    http://auth-server;
        proxy_pass_request_body off;
        proxy_set_header 	    Content-Length "";
        proxy_set_header 	    X-Original-URI $request_uri;
    }
    • auth_request 지시자의 매개변수로 내부 인증 시스템의 위치를 가리키는 URI를 지정합니다.
    • auth_request_set 지시자는 인증을 위한 하위 요청의 응답으로 받은 값을 매개변수에 지정합니다.
    • proxy_pass_request_body 지시자를 off로 설정해서 바디를 사용하지 않으면 인증 요청의 크기와 처리 시간이 줄어들고, 바디가 없어지므로 Content-Length 헤더를 빈 값이 되어야 합니다.
    • 인증 서비스에 접근하는 하위 요청에서 특정 응답 헤더나 정보를 저장해둬야 한다면 auth_request_set 지시자를 사용해 응답 데이터를 새로운 변숫값으로 만들 수 있습니다.

     

     

    3. JWT 검증하기 (엔진엑스 플러스)


    엔진엑스 플러스의 JWT 인증 모듈을 사용해 토근의 시그니처(signature)를 검증하고 JWT 속성 정보(claim)과 헤더를 엔진엑스 변수로 가져옵니다.

    location /api/ {	
        auth_jwt "api";
        auth_jwt_key_file conf/keys.json;
    }
    • 이 설정은 location 블록으로 분기된 요청에 대해 JWT 검증을 수행합니다.
    • auth_jwt 지시자는 인증 헤더의 인증 범위 선언에 사용할 문자열을 매개변수로 사용하고(?) JWT를 저장할 매개변수를 추가로 지정할 수도 있습니다.
    • JWT 표준에 따라 Authentication 헤더가 기본으로 사용됩니다.
    • 인증을 끄려면 auth_jwt 지시자의 매개변수를 off로 지정합니다.
    • auth_jwt_key_file 지시자는 하나의 매개변수를 받으며 이 매개변수는 표준 JWK(JSON web key) 형식으로 만들어진 키 파일의 경로입니다.

     

     

    4. JSON 웹 키 생성하기 (엔진엑스 플러스)


    엔진엑스 플러스는 RFC 표준으로 제정된 JWK 형식을 사용합니다. 표준에 따르면 JWK 파일은 키 객체를 여러 개 포함하는 배열을 가질 수 있습니다.

    {"keys":
        [
            {
                "kty": "oct",
                "kid": "0001",
                "k": "OctetSequenceKeyValue"
            },
            {
                "kty": "EC",
                "kid": "0002",
                "crv": "P-256",
                "x": "XCoordinateValue",
                "y": "YCoordinateValue",
                "d": "PrivateExponent",
                "use", "sig"
            },
            {	
                "kty": "RSA",
                "kid": "0003",
                "n": "Modulus",
                "e": "Exponent",
                "d": "PrivateExponent"
            }
        ]
    }
    • 예시는 RFC 표준에서 언급 된 세 가지 기본 키 타입을 모두 포함합니다.
    • kty 속성은 키 타입을 나타내며 예시에서 사용한 세 가지 키 형식은 옥텟 시퀀스(oct), 타원곡선(EC), RSA 입니다.
    • kid 속성은 키 ID를 말합니다.

     

     

    5. JSON 웹 토큰 검증하기 (엔진엑스 플러스)


    엔진엑스 플러스에서 제공하는 JWT 모듈을 location, server 블록에서 사용하고 auth_jwt 지시자가 $cookie_auth_token 변수에 저장된 토큰값을 검증할 수 있습니다.

    location /private/ {	
        auth_jwt "Google Oauth" token=$cookie_auth_token;
        auth_jwt_key_file /etc/nginx/google_certs.jwt;
    }
    • 예시는 엔진엑스  플러스로 구글 OAuth 2.0 오픈아이디 커넥트의 JWT를 검증하는 방법을 보여줍니다.
    • /private/ 경로에 접근하는 요청에 대해 JWT 검증을 하며 검증할 토큰은 auth_jwt 지시자를 사용해 $cookie_auth_token 변수를 참조합니다.
    • 구글 OAuth 2.0 오픈아이디 커넥트는 기본 bearer 토큰을 사용하지 않고 auth_token 쿠키를 사용하기 때문에 엔진엑스가 기본 경로를 사용하지 않고 이 쿠키를 찾아 토큰값을 사용하도록 해야 합니다.

     

     

    6. JSON 웹 키 세트 획득 자동화와 캐싱 (엔진엑스 플러스)


     

    캐시 영역과 auth_jwt_key_request 지시자를 사용해서 자동으로 키가 현행회되도록 합니다.

    proxy_cache_path /data/nginx/cache levels=1 keys_zone=foo:10m;
    
    server {
        location / {
        	auth_jwt "closed site";
            auth_jwt_key_request /jwts_uri;
        }
        
        location = /jwts_uri {   	
            internal;
            proxy_cache foo;
            proxy_pass https://idp.example.com/keys;
        }
    }
    • auth_jwt_key_request 지시자는 엔진엑스 플러스가 internal로 선언된 하위 요청을 통해 JWKS를 가져오도록 합니다.
    • 하위 요청은 idp로 요청을 위임하기 위해 /jwts_uri로 보내지고 이 요청은 과부화를 막기 위해 10분간 캐시됩니다.
    • 이 기능은 인증 요청이 발생하면 엔진엑스 플러스 서버가 가진 JWKS를 동적으로 업데이트합니다.

     

     

    7. 오픈아이디 커넥트 SSO를 통한 사용자 인증 (엔진엑스 플러스)


    오픈아이디 커넥트 신원 확인 서비스 제공자(IdP)를 엔진엑스 플러스에 연동하여 인증할 수 있습니다.

     

    • 우선 IdP가 오픈아이디 커넥트 1.0을 지원해야 하고, 엔진엑스  플러스는 권한 부여 흐름에서 볼 때 OIDC로 요청을 전달하는 역할을 합니다.
    • 연동 작업은 최신 절차를 따라야 하기 때문에 깃허브에 소개된 예시 설정과 코드를 참고해야 합니다.
    • 접근이 제한된 리소스로 인증되지 않은 요청이 들어오면 엔진엑스는 IdP를 통해 요청에 대한 인증을 먼저 수행하도록 하는데 IdP들은 각자 로그인 절차를 수행하고 인증 코드를 엔진엑스로 보냅니다.
    • 인증이 완료되면 엔진엑스는 인증 코드를 ID 토큰으로 활용해서 IdP와 직접 통신합니다.
    • 이 토큰은 JWT를 통해 검증이 되고 엔진엑스의 키-값 저장소에 보관됩니다.
    • 이 과정에서 엔진엑스는 클라이언트에 대한 세션 쿠키를 생성하고 키-값 저장소에서 토큰을 사용하는데 이용합니다.
    • 클라이언트의 이후 요청은 쿠키값을 통해 검증이 되고 필요시 키-값 저장소에서 ID 토큰을 찾아 활용합니다.
    반응형
Designed by Tistory.