Keystoneauth 세션 사용

Jmnote (토론 | 기여)님의 2024년 6월 22일 (토) 17:14 판 (→‎로깅)

1 개요

Using Sessions
세션 사용

https://docs.openstack.org/keystoneauth/latest/using-sessions.html

Crystal Clear action info.png 작성 중인 문서입니다.


2 소개

keystoneauth1.session.Session 클래스는 다양한 서비스 간에 공통 인증 및 요청 매개변수를 공유하는 다양한 OpenStack 클라이언트에 통일된 인터페이스를 제공하기 위해 keystoneauth1에 도입되었습니다.

Session과 인증 플러그인을 사용하는 모델과 일반적인 용어는 requests 라이브러리에서 많은 영감을 받았습니다. 그러나 Session 클래스나 인증 플러그인이 requests 라이브러리의 개념에 직접적으로 의존하지 않기 때문에 직접적인 변환을 기대해서는 안 됩니다.

2.1 기능

  • 공통 클라이언트 인증
인증은 다양한 인증 플러그인 중 하나에 의해 처리되며, 이 인증 정보는 동일한 Session 객체를 사용하는 모든 서비스 간에 공유됩니다.
  • 보안 유지관리
보안 코드는 단일 장소에서 유지관리되며 모든 클라이언트 간에 재사용되므로 문제가 발생할 경우 단일 위치에서 수정할 수 있습니다.
  • 표준 서비스 및 버전 발견
클라이언트는 ID 토큰이나 기타 형태의 신원확인 자격증명에 대한 지식을 필요로 하지 않습니다. 서비스, 엔드포인트, 주요 버전 검색 및 마이크로 버전 지원 검색은 Session 및 플러그인에 의해 처리됩니다. 발견 정보는 메모리에 자동으로 캐시되므로 사용자는 과도한 발견 메타데이터 사용에 대해 걱정할 필요가 없습니다.
  • 안전한 HTTP 상호작용 로깅
클라이언트는 HTTP 상호작용의 로깅을 활성화할 수 있어야 하지만, 토큰이나 비밀 정보와 같은 일부 항목은 생략해야 합니다.

3 사용자용 세션

Session 객체는 OpenStack 클라우드 서비스에 대한 접점입니다. 이 객체는 인증 자격증명과 OpenStack과 통신하는 데 필요한 연결 정보를 저장하여 여러 서비스와 통신하는 데 재사용할 수 있습니다. 서비스 생성 시 이 Session 객체가 클라이언트에 전달되어 해당 정보를 사용할 수 있습니다.

세션은 필요할 때 인증을 수행합니다. 인증이 필요한 요청이 세션을 통해 전달되면 인증 플러그인은 유효한 토큰을 요청합니다. 유효한 토큰이 있으면 사용되고, 그렇지 않은 경우 인증 플러그인이 인증 서비스에 연락하여 새 토큰을 가져올 수 있습니다.

Session을 사용하는 keystoneclient 예제:

from keystoneauth1.identity import v3
from keystoneauth1 import session
from keystoneclient.v3 import client

auth = v3.Password(auth_url='https://my.keystone.com:5000/v3',
                   username='myuser',
                   password='mypassword',
                   project_name='proj',
                   user_domain_id='default',
                   project_domain_id='default')
sess = session.Session(auth=auth,
                       verify='/path/to/ca.cert')
ks = client.Client(session=sess)
users = ks.users.list()

다른 OpenStack 클라이언트 라이브러리도 이와 유사한 방식으로 세션 객체를 클라이언트 생성자에 전달하여 생성됩니다.

3.1 인증 플러그인 공유

세션은 하나의 인증 플러그인만 포함할 수 있습니다. 그러나 인증 플러그인이 그 세션에 구체적으로 묶여 있는 것은 아니므로, 기존 인증 플러그인을 재사용하여 새로운 세션을 만들 수 있습니다:

new_sess = session.Session(auth=sess.auth,
                           verify='/path/to/different-cas.cert')

이 경우, 인증 호출을 수행할 때 어떤 세션 객체가 사용될지 알 수 없으므로 명령은 어느 세션에서도 성공할 수 있어야 합니다.

인증 플러그인은 요청별로도 제공될 수 있습니다. 이는 하나의 세션이 여러 인증 자격증명을 다루는 상황에서 유용합니다:

sess.get('https://my.keystone.com:5000/v3',
         auth=my_auth_plugin)

인증 플러그인이 매개변수를 통해 제공되면 세션의 인증 플러그인을 무시하고 해당 플러그인이 우선 사용됩니다.

4 클라이언트 개발자용 세션

세션은 인증 데이터 및 토큰 형식 처리를 간소화하여 클라이언트가 엔드포인트를 선택하기 위한 필터 매개변수를 지정하고 카탈로그의 구문 분석을 쉽게 관리할 수 있도록 돕습니다.

4.1 메이저 버전 발견과 마이크로버전 지원

OpenStack에서 사용 가능한 서비스의 루트 URL은 사용자가 받는 토큰의 일부인 서비스 카탈로그라는 객체에 포함되어 배포됩니다. 클라이언트는 제공된 URL을 사용하는 대신 서비스 카탈로그에서 URL을 가져와야 합니다. 특정 서비스의 루트 URL은 서비스의 엔드포인트라고 하며, 특정 버전의 서비스 URL은 버전화된 엔드포인트라고 합니다. 서비스에 대한 REST 요청은 주어진 버전화된 엔드포인트에 대해 수행됩니다.

주요 API 버전과 마이크로버전 주제는 혼란스러울 수 있습니다. keystoneauth는 주요 API 버전과 연결된 버전화된 엔드포인트 발견 및 해당 엔드포인트가 지원하는 마이크로버전에 대한 정보 가져오기 기능을 제공하므로, 두 가지의 차이점을 이해하는 것이 중요합니다.

개념적으로 가장 중요한 것은 주요 API 버전이 개별 버전화된 엔드포인트의 URL을 설명하는 반면, 주어진 버전화된 엔드포인트는 지원하는 마이크로버전 범위를 표현할 수 있다는 점입니다.

사용자가 서비스에 대해 REST 요청을 하고자 할 때, 사용자는 주요 API 버전과 서비스 유형을 명시하여 적절한 버전화된 엔드포인트를 찾고 사용합니다. 예를 들어, 사용자가 cloud.example.com에서 버전 2의 컴퓨트 서비스를 요청하면 https://compute.example.com/v2라는 버전화된 엔드포인트를 얻게 됩니다.

각 서비스는 각 버전화된 엔드포인트의 루트에 해당 버전화된 엔드포인트에 대한 정보를 포함하는 발견 문서를 제공합니다. 또한 각 서비스는 모든 사용가능한 버전화된 엔드포인트의 발견 문서 목록을 포함하는 문서를 비-버전화된 엔드포인트의 루트에 제공합니다. 이러한 문서를 통해 사용자가 원하는 주요 API 버전에 해당하는 버전화된 엔드포인트를 찾을 수 있습니다.

각 문서는 또한 해당 버전화된 엔드포인트가 이해하는 최소 및 최대 마이크로버전을 나열하여 지원하는 마이크로버전을 나타낼 수 있습니다. 요청된 주요 API 버전에 대한 버전화된 엔드포인트를 찾은 결과로, 사용자는 해당 버전화된 엔드포인트에서 사용할 수 있는 마이크로버전을 알 수 있습니다.

클라이언트가 주요 API 버전의 엔드포인트에 REST 요청을 할 때, 클라이언트는 선택적으로 개별 요청마다 헤더에 특정 마이크로버전을 사용하도록 명시할 수 있습니다. 클라이언트가 마이크로버전을 요청하지 않으면 서비스는 최소 지원 마이크로버전이 지정된 것처럼 동작합니다.

전체 거래는 세 부분으로 구성됩니다:

  • 주어진 서비스의 주요 API 버전에 대한 엔드포인트는 무엇인가?
  • 해당 엔드포인트에서 지원하는 최소 및 최대 마이크로버전은 무엇인가?
  • 사용자가 특정 요청에 대해 사용하고자 하는 마이크로버전 범위는 무엇인가?

keystoneauth는 주어진 서비스의 주요 API 버전에 대한 엔드포인트를 발견하고, 해당 엔드포인트가 지원하는 마이크로버전 범위를 보고하는 기능을 제공합니다.

마이크로버전카탈로그 소비에 대한 자세한 정보는 API-WG 스펙에서 확인할 수 있습니다.

4.2 인증

Session 객체를 사용하여 요청을 보낼 때, 키워드 매개변수로 authenticated를 전달하여 토큰이 포함되어야 하는지 여부를 지정할 수 있습니다. 기본적으로 인증 플러그인이 사용가능한 경우 토큰이 포함됩니다:

# Keystone에서는 기본적으로 이 라우트가 보호되지 않습니다
resp = sess.get('https://my.keystone.com:5000/v3',
                    authenticated=False)

4.3 서비스 발견

일반적으로 클라이언트는 통신하는 서버의 전체 URL을 알 필요가 없으며, 단순히 올바른 서비스에 속하는 경로로 요청을 보내면 됩니다. 이는 요청의 endpoint_filter 매개변수로 제어되며, 인증 플러그인이 요청을 보낼 올바른 URL을 결정하는 데 필요한 모든 정보를 포함합니다. 이 모드를 사용할 때는 요청 경로만 지정하면 됩니다.

resp = session.get('/users',
                       endpoint_filter={'service_type': 'identity',
                                        'interface': 'admin',
                                        'region_name': 'myregion',
                                        'min_version': '2.0',
                                        'max_version': '3.4',
                                        'discover_versions': False})

Note

이 예시에서 min_version과 max_version 인수는 주어진 메이저 API 버전에 대한 엔드포인트를 찾기 위한 허용 범위를 나타냅니다. 이들은 endpoint_filter에 있으며, /users 호출을 특정 마이크로버전으로 요청하는 것이 아닙니다.

endpoint_filter가 수락하는 인수들:

service_type
서비스 유형. 예를 들어, <code<identity, compute, volume 등 여러 사전정의된 식별자가 있습니다.
interface
인터페이스의 네트워크 노출. 리스트로도 지정할 수 있으며, 이 경우 매치하는 첫 번째 인터페이스가 사용됩니다. 유효한 값은 다음과 같습니다:
  • public: 인터넷 또는 네트워크에 공개된 엔드포인트.
  • internal: 사설 네트워크 내에서만 접근 가능한 엔드포인트.
  • admin: 관리 작업에 사용되는 엔드포인트.
region_name
엔드포인트가 위치한 지역의 이름.
version
주어진 주요 API에 대해 최소 버전. 예를 들어, 2.2 버전은 2.22.3과 일치하지만 2.1이나 3.0과는 일치하지 않습니다. min_version 및 max_version과 상호 배타적입니다.
min_version
주어진 API의 최소 버전, max_version과 함께 범위의 하한으로 사용됩니다. version과 상호 배타적입니다.
max_version
주어진 API의 최대 버전, min_version과 함께 범위의 상한으로 사용됩니다. 예시:
'min_version': '2.2',
'max_version': '3.3'
이는 2.2, 2.10, 3.0, 3.3 버전과 일치하지만, 1.42, 2.1, 3.20과는 일치하지 않습니다. version과 상호 배타적입니다.

Note

version, min_version, max_version는 모두 주어진 주요 API 버전의 서비스 엔드포인트를 결정하는 데 사용됩니다.

discover_versions
버전 발견 API가 반드시 필요하지 않더라도 실행할지 여부를 결정합니다. 엔드포인트 요청을 카탈로그만으로 충족할 수 있는 경우가 많아, 버전 발견 API 호출이 추가적으로 낭비될 수 있습니다. 그러나 추론 대신 발견을 실행하는 것이 바람직할 수도 있습니다. 기본값은 True입니다.

모든 버전 인수(version, min_version 및 max_version)는 다음과 같이 제공될 수 있습니다:

  • string: '2.0'
  • int: 2
  • float: 2.0
  • int 튜플: (2, 0)

version과 max_version은 최신 가용 버전을 나타내는 latest 문자열로도 제공될 수 있습니다.

엔드포인트 필터는 단순한 키-값 필터이며 원하는 만큼의 인수를 제공할 수 있습니다. 인증 플러그인이 이해하는 매개변수를 올바르게 사용하는 것은 인증 플러그인의 역할입니다.

실험적 API를 허용하거나 지원중단된 API를 허용하지 않도록 서비스 탐색을 더 제한하려면 allow 매개변수를 사용할 수 있습니다:

resp = session.get('/<project-id>/volumes',
                       endpoint_filter={'service_type': 'volume',
                                        'interface': 'public',
                                        'version': 1},
                       allow={'allow_deprecated': False})

allow가 인식하는 발견가능한 엔드포인트 유형은 다음과 같습니다:

  • allow_deprecated: 지원중단된 버전 엔드포인트 허용.
  • allow_experimental: 실험적 버전 엔드포인트 허용.
  • allow_unknown: 인식되지 않은 상태의 엔드포인트 허용.

Session 객체는 필터와 일치하는 URL을 결정하고 제공된 경로에 이를 추가하여 유효한 요청을 생성합니다. 여러 URL이 일치하는 경우 임의의 URL이 선택될 수 있습니다.

인증 플러그인은 endpoint_filter에 대해 일관된 매개변수 세트를 유지하려고 노력하겠지만, 인증 플러그인의 개념은 의도적으로 일반적입니다. 특정 메커니즘이 특정 인수를 해석하는 방법을 모를 경우 이를 무시할 수 있습니다. 예를 들어 keystoneauth1.token_endpoint.Token 플러그인(특정 엔드포인트와 토큰 조합을 항상 사용하려는 경우 사용)은 endpoint_filter 매개변수와 상관없이 항상 동일한 엔드포인트를 반환합니다. 또는 커스텀 OpenStack 인증 메커니즘은 여러 인터페이스 옵션의 개념이 없어 해당 매개변수를 무시할 수 있습니다.

사용자는 자신이 사용하는 인증 시스템의 제한사항을 이해하고 있어야 합니다.

4.4 어댑터 사용

개발자가 매번 API 호출 시에 endpoint_filter를 제공하고 싶지 않다면, keystoneauth1.adapter.Adapter를 생성할 수 있습니다. Adapter 생성자는 endpoint_filter와 동일한 인자와 Session을 인자로 받습니다. 어댑터는 endpoint_filter에 의해 발견되는 엔드포인트에 "마운트"되는 Session과 매우 유사하게 동작하며, 동일한 REST 메서드를 제공합니다.

adapter = keystoneauth1.adapter.Adapter(
    session=session,
    service_type='volume',
    interface='public',
    version=1)
response = adapter.get('/volumes')

Session의 endpoint_filter와 마찬가지로, version, min_version, max_version 매개변수는 서비스의 Major API에 적합한 엔드포인트를 결정하는 데 도움을 줍니다.

4.5 엔드포인트 메타데이터

keystoneauth1.adapter.Adapterkeystoneauth1.session.Session에는 주어진 서비스에 대해 발견된 엔드포인트의 메타데이터를 가져오는 메소드인 get_endpoint_data가 있습니다.

keystoneauth1.session.Session에서는 이 메소드가 endpoint_filter와 동일한 인수를 받습니다.

keystoneauth1.adapter.Adapter에서는 이 메소드가 인수를 받지 않으며, 어댑터가 장착된 엔드포인트에 대한 정보를 반환합니다.

get_endpoint_datakeystoneauth1.discovery.EndpointData 객체를 반환합니다. 이 객체는 발견된 엔드포인트에 대한 메이저 api_versin 또는 inferface 정보를 찾는 데 사용할 수 있습니다. 또한 입력값 목록 또는 latest 버전의 범위에 대한 정보를 제공합니다.

이 객체는 API에서 지원하는 min_microversion 및 max_microversion 값을 확인하는 데도 사용할 수 있습니다. API가 마이크로버전을 지원하지 않는 경우, 이 값들은 None이 됩니다. 또한 엔드포인트에 next_min_version과 not_before 값이 존재하는 경우 해당 값을 포함하며, 존재하지 않으면 None이 됩니다. keystoneauth1.discovery.EndpointData 객체는 REST 문서에 마이크로버전 관련 속성이 포함되지 않았더라도 항상 마이크로버전 관련 속성을 포함합니다.

get_endpoint_data는 다른 발견 프로세스와 동일한 캐시를 사용하므로 호출 시 부당한 비용이 발생하지 않습니다. 기본적으로 이 메소드는 마이크로버전 메타데이터를 가져오기 위해 적어도 한 번의 버전 발견 호출을 수행합니다. 사용자가 서비스가 마이크로버전을 지원하지 않는다는 것을 알고 주요 버전이 무엇인지 궁금한 경우, discover_versionsFalse로 설정하여 마이크로버전 메타데이터 가져오기를 방지할 수 있습니다.

4.6 마이크로버전 요청

사용자가 주어진 요청에 대해 마이크로버전을 지정하려는 경우, keystoneauth1.session.Session 객체 또는 keystoneauth1.adapter.Adapter 객체의 요청 메서드에 microversion 매개변수를 전달할 수 있습니다. 이를 통해 keystoneauth는 사용자가 원하는 마이크로버전을 서비스에 알리는 적절한 헤더를 서비스에 전달하게 됩니다.

resp = session.get('/volumes',
                   microversion='3.15',
                   endpoint_filter={'service_type': 'volume',
                                    'interface': 'public',
                                    'min_version': '3',
                                    'max_version': 'latest'})

사용자가 keystoneauth1.adapter.Adapter를 사용하는 경우, microversion 헤더에 포함되는 service_type은 Adapter의 service_type에서 가져옵니다.

adapter = keystoneauth1.adapter.Adapter(
    session=session,
    service_type='compute',
    interface='public',
    min_version='2.1')
response = adapter.get('/servers', microversion='2.38')

사용자는 Adapter 생성자에 default_microversion 매개변수를 제공하여 명시적인 마이크로버전이 요청되지 않은 모든 요청에서 이를 사용할 수 있습니다.

adapter = keystoneauth1.adapter.Adapter(
    session=session,
    service_type='compute',
    interface='public',
    min_version='2.1',
    default_microversion='2.38')
response = adapter.get('/servers')

사용자가 keystoneauth1.session.Session을 사용하는 경우, service_type은 endpoint_filter의 service_type에서 가져옵니다.

만약 서비스에 대한 마이크로버전 헤더에 사용되는 service_type이 올바르지 않은 경우, microversion_service_type 매개변수를 사용할 수 있습니다. 예를 들어, keystoneauth는 이미 Cinder에 대해 알고 있지만, Cinder의 service_type은 block-storage이며 마이크로버전 헤더는 volume을 기대합니다.

# Cinder와의 상호작용에서는 microversion_service_type을 명시적으로 오버라이드할 필요가 없습니다.
# 이 예시는 매개변수 사용법을 설명하기 위한 것입니다.
resp = session.get('/volumes',
                   microversion='3.15',
                   microversion_service_type='volume',
                   endpoint_filter={'service_type': 'block-storage',
                                    'interface': 'public',
                                    'min_version': '3',
                                    'max_version': 'latest'})

5 로깅

로깅 시스템은 예상대로 keystoneauth 네임스페이스를 기준으로 표준 파이썬 로깅을 사용합니다. HTTP 상호작용에 대한 로그 메시지가 기록되는 위치에는 두 가지 가능성이 있습니다.

기본적으로 모든 메시지는 keystoneauth.session 로거로 전송됩니다.

keystoneauth1.session.Session 생성자의 split_loggers 옵션이 True로 설정되면, HTTP 콘텐츠가 네 개의 하위 로거로 분할되어 기록됩니다. 이를 통해 기록되는 내용과 방법을 세밀하게 제어할 수 있습니다:

keystoneauth.session.request-id
URL, service-type, request-id에 대한 정보를 포함하여 각 HTTP 요청마다 DEBUG 수준의 로그 엔트리를 기록합니다.
keystoneauth.session.request
각 HTTP 요청마다 curl 형식의 요청 문자열을 포함하여 DEBUG 수준의 로그 엔트리를 기록합니다.
keystoneauth.session.response
상태 코드 및 수신된 헤더를 포함하여 수신된 각 HTTP 응답마다 DEBUG 수준의 로그 엔트리를 기록합니다.
keystoneauth.session.body
content-typetext 또는 json인 경우 응답 본문의 내용을 포함하여 DEBUG 수준의 로그 엔트리를 기록합니다.

5.1 로거 사용

5.2 사용자 제공 로거

keystoneauth1.session.Session 및 keystoneauth1.adapter.Adapter의 HTTP 메소드(request, get, post, put 등)는 모두 logger 매개변수를 지원합니다. 사용자는 이를 통해 자신의 로거를 제공할 수 있으며, 이 경우 위에서 언급한 세션 로거를 대체합니다. 이렇게 제공된 단일 로거를 사용하면 요청, 응답 및 본문 내용이 모두 DEBUG 레벨에서 해당 로거에 기록되며, 적절히 REQ:, RESP:, RESP BODY: 문자열이 앞에 추가됩니다.

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}