OAuth 2.0 액세스 토큰 인증

OAuth 2.0 액세스 토큰 인증 (Authentication using OAuth 2.0 access tokens)

Pulsar는 OAuth 2.0 액세스 토큰으로 클라이언트를 인증하는 것을 지원해요. OAuth 2.0 인증 서비스(토큰 발급자 역할)에서 얻은 액세스 토큰으로 Pulsar 클라이언트를 식별하고, 토픽에 메시지를 게시하거나 토픽에서 메시지를 소비하는 것 같은 특정 작업을 허용받는 "주체(principal)"(또는 "역할(role)")과 연결할 수 있어요.

출처: 문서

본문

OAuth 2.0 서버와 통신한 뒤 Pulsar 클라이언트는 서버에서 액세스 토큰을 받아 이 액세스 토큰을 브로커에 전달해 인증해요. 기본적으로 브로커는 org.apache.pulsar.broker.authentication.AuthenticationProviderToken을 사용할 수 있어요. 또는 AuthenticationProvider의 값을 커스터마이즈할 수도 있어요.

브로커/프록시에서 OAuth2 인증 활성화 (Enable OAuth2 authentication on brokers/proxies)

브로커/프록시가 OAuth2로 클라이언트를 인증하도록 구성하려면 conf/broker.confconf/proxy.conf 파일에 다음 파라미터를 추가해요. standalone Pulsar를 사용한다면 conf/standalone.conf 파일에 이 파라미터를 추가해야 해요.

# Configuration to enable authentication
authenticationEnabled=true
authenticationProviders=org.apache.pulsar.broker.authentication.AuthenticationProviderToken
# Authentication settings of the broker itself. Used when the broker connects to other brokers, or when the proxy connects to brokers, either in same or other clusters
brokerClientAuthenticationPlugin=org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2
brokerClientAuthenticationParameters={"privateKey":"file:///path/to/privateKey","audience":"https://dev-kt-aa9ne.us.auth0.com/api/v2/","issuerUrl":"https://dev-kt-aa9ne.us.auth0.com"}
# brokerClientAuthenticationParameters={"privateKey":"data:application/json;base64,privateKey-body-to-base64","audience":"https://dev-kt-aa9ne.us.auth0.com/api/v2/","issuerUrl":"https://dev-kt-aa9ne.us.auth0.com"}
# If using secret key (Note: key files must be DER-encoded)
tokenSecretKey=file:///path/to/secret.key
# The key can also be passed inline:
# tokenSecretKey=data:;base64,FLFyW0oLJ2Fi22KKCm21J18mbAdztfSHN/lAT5ucEKU=
# If using public/private (Note: key files must be DER-encoded)
# tokenPublicKey=file:///path/to/public.key

Pulsar 클라이언트에서 OAuth2 인증 구성 (Configure OAuth2 authentication in Pulsar clients)

다음 Pulsar 클라이언트에서 OAuth2 인증 제공자를 사용할 수 있어요.

  • Java
  • Python
  • C++
  • Node.js
  • Go

Java:

import org.apache.pulsar.client.impl.auth.oauth2.AuthenticationFactoryOAuth2;
URL issuerUrl = new URL("https://dev-kt-aa9ne.us.auth0.com");
URL credentialsUrl = new URL("file:///path/to/KeyFile.json");
String audience = "https://dev-kt-aa9ne.us.auth0.com/api/v2/";
PulsarClient client = PulsarClient.builder()
    .serviceUrl("pulsar://broker.example.com:6650/")
    .authentication(
        AuthenticationFactoryOAuth2.clientCredentialsBuilder.issuerUrl(issuerUrl)
          .credentialsUrl(credentialsUrl).audience(audience).build())
    .build();

추가로 인코딩된 파라미터를 사용해 Pulsar Java 클라이언트 인증을 구성할 수도 있어요.

Authentication auth = AuthenticationFactory
    .create(AuthenticationOAuth2.class.getName(), "{\"type\":\"client_credentials\",\"privateKey\":\"./key/path/..\",\"issuerUrl\":\"...\",\"audience\":\"...\"}");
PulsarClient client = PulsarClient.builder()
    .serviceUrl("pulsar://broker.example.com:6650/")
    .authentication(auth)
    .build();

Python:

from pulsar import Client, AuthenticationOauth2
params = '''{
    "issuer_url": "https://dev-kt-aa9ne.us.auth0.com",
    "private_key": "/path/to/privateKey",
    "audience": "https://dev-kt-aa9ne.us.auth0.com/api/v2/"
}'''
client = Client("pulsar://my-cluster:6650", authentication=AuthenticationOauth2(params))

C++:

#include <pulsar/Client.h>
pulsar::ClientConfiguration config;
std::string params = R"({
    "issuer_url": "https://dev-kt-aa9ne.us.auth0.com",
    "private_key": "../../pulsar-broker/src/test/resources/authentication/token/cpp_credentials_file.json",
    "audience": "https://dev-kt-aa9ne.us.auth0.com/api/v2/"
})";
config.setAuth(pulsar::AuthOauth2::create(params));
pulsar::Client client("pulsar://broker.example.com:6650/", config);

Node.js:

    const Pulsar = require('pulsar-client');
    const issuer_url = process.env.ISSUER_URL;
    const private_key = process.env.PRIVATE_KEY;
    const audience = process.env.AUDIENCE;
    const scope = process.env.SCOPE;
    const service_url = process.env.SERVICE_URL;
    const client_id = process.env.CLIENT_ID;
    const client_secret = process.env.CLIENT_SECRET;
    (async () => {
      const params = {
        issuer_url: issuer_url
      }
      if (private_key.length > 0) {
        params['private_key'] = private_key
      } else {
        params['client_id'] = client_id
        params['client_secret'] = client_secret
      }
      if (audience.length > 0) {
        params['audience'] = audience
      }
      if (scope.length > 0) {
        params['scope'] = scope
      }
      const auth = new Pulsar.AuthenticationOauth2(params);
      // Create a client
      const client = new Pulsar.Client({
        serviceUrl: service_url,
        tlsAllowInsecureConnection: true,
        authentication: auth,
      });
      await client.close();
    })();

note OAuth2 인증 지원은 Node.js 클라이언트 1.6.2 이상 버전에서만 사용할 수 있어요.

Go:

oauth := pulsar.NewAuthenticationOAuth2(map[string]string{
		"type":       "client_credentials",
		"issuerUrl":  "https://dev-kt-aa9ne.us.auth0.com",
		"audience":   "https://dev-kt-aa9ne.us.auth0.com/api/v2/",
		"privateKey": "/path/to/privateKey",
		"clientId":   "0Xx...Yyxeny",
	})
client, err := pulsar.NewClient(pulsar.ClientOptions{
		URL:              "pulsar://my-cluster:6650",
		Authentication:   oauth,
})

CLI 도구에서 OAuth2 인증 구성 (Configure OAuth2 authentication in CLI tools)

이 섹션은 OAuth2 인증 플러그인으로 클러스터에 연결하기 위해 Pulsar CLI 도구를 사용하는 방법을 설명해요.

  • pulsar-admin
  • pulsar-client
  • pulsar-perf

pulsar-admin:

bin/pulsar-admin --admin-url https://streamnative.cloud:443 \
    --auth-plugin org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2 \
    --auth-params '{"privateKey":"file:///path/to/key/file.json",
        "issuerUrl":"https://dev-kt-aa9ne.us.auth0.com",
        "audience":"https://dev-kt-aa9ne.us.auth0.com/api/v2/"}' \
    tenants list

pulsar-client:

bin/pulsar-client \
    --url SERVICE_URL \
    --auth-plugin org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2 \
    --auth-params '{"privateKey":"file:///path/to/key/file.json",
        "issuerUrl":"https://dev-kt-aa9ne.us.auth0.com",
        "audience":"https://dev-kt-aa9ne.us.auth0.com/api/v2/"}' \
    produce test-topic -m "test-message" -n 10

pulsar-perf:

bin/pulsar-perf produce --service-url pulsar+ssl://streamnative.cloud:6651 \
    --auth-plugin org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2 \
    --auth-params '{"privateKey":"file:///path/to/key/file.json",
        "issuerUrl":"https://dev-kt-aa9ne.us.auth0.com",
        "audience":"https://dev-kt-aa9ne.us.auth0.com/api/v2/"}' \
    -r 1000 -s 1024 test-topic
  • admin-url 파라미터를 웹 서비스 URL로 설정해요. 웹 서비스 URL은 프로토콜, 호스트 이름, 포트 ID의 조합이에요. 예: pulsar://localhost:6650.
  • privateKey, issuerUrl, audience 파라미터를 키 파일의 구성에 따른 값으로 설정해요. 자세한 내용은 authentication types를 참고해요.

인증 유형 (Authentication types)

현재 Pulsar 클라이언트는 client_credentials 인증 유형만 지원해요. 인증 유형은 OAuth 2.0 인증 서비스를 통해 액세스 토큰을 얻는 방법을 결정해요.

다음 표는 client_credentials 인증 유형의 파라미터를 정리한 것이에요.

| 파라미터 | 설명 | 예시 | 필수 여부 | | type | OAuth 2.0 인증 유형. | client_credentials (기본값) | 선택 | | issuerUrl | Pulsar 클라이언트가 액세스 토큰을 얻을 수 있게 하는 인증 제공자의 URL. | https://accounts.google.com | 필수 | | privateKey | JSON 자격 증명 파일의 URL. | 다음 패턴 형식 지원:
file:///path/to/file file:/path/to/file data:application/json;base64,<base64-encoded value> | 필수 | | audience | Pulsar 클러스터의 OAuth 2.0 "리소스 서버" 식별자. | https://broker.example.com | 선택 | | scope | 액세스 요청의 범위.
자세한 내용은 access token scope를 참고해요. | api://pulsar-cluster-1/.default | 선택 | | connectTimeout | java.time.Duration 형식의 HTTP 연결 타임아웃. 기본값: PT10S. Java 클라이언트에서만 구현됨. | PT10S | 선택 | | readTimeout | java.time.Duration 형식의 HTTP 읽기 타임아웃. 기본값: PT30S. Java 클라이언트에서만 구현됨. | PT30S | 선택 | | trustCertsFilePath | 토큰 발급자의 신뢰 인증서 파일 경로. 설정하지 않으면 JVM의 기본 트러스트 스토어를 사용해요. Java 클라이언트에서만 구현됨. | /path/to/file | 선택 | | wellKnownMetadataPath | 인증 서버 메타데이터의 경로. 설정하지 않으면 OIDC의 well-known URI 접미사를 사용해요. /.well-known/openid-configuration을 사용한다면 사전 구성된 AuthenticationOAuth2StandardAuthzServer 클래스와 clientCredentialsWithStandardAuthzServerBuilder 빌더가 유용해요. Java 클라이언트에서만 구현됨. | /.well-known/path | 선택 |

자격 증명 파일 credentials_file.json은 클라이언트 인증 유형과 함께 사용되는 서비스 계정 자격 증명을 포함해요. 다음은 자격 증명 파일의 예시예요. 인증 유형은 기본적으로 client_credentials로 설정되고, "client_id"와 "client_secret" 필드는 필수예요.

{
  "type": "client_credentials",
  "client_id": "d9ZyX97q1ef8Cr81WHVC4hFQ64vSlDK3",
  "client_secret": "on1uJ...k6F6R",
  "client_email": "1234567890-abcdefghijklmnopqrstuvwxyz@developer.gserviceaccount.com",
  "issuer_url": "https://accounts.google.com"
}

다음은 OAuth2 서버에서 액세스 토큰을 얻기 위해 사용되는 일반적인 원본 OAuth2 요청의 예시예요.

curl --request POST \
  --url https://dev-kt-aa9ne.us.auth0.com/oauth/token \
  --header 'content-type: application/json' \
  --data '{
  "client_id":"Xd23RHsUnvUlP7wchjNYOaIfazgeHd9x",
  "client_secret":"rT7ps7WY8uhdVuBTKWZkttwLdQotmdEliaM5rLfmgNibvqziZ-g07ZH52N_poGAb",
  "audience":"https://dev-kt-aa9ne.us.auth0.com/api/v2/",
  "grant_type":"client_credentials"}'

위 예시에서 매핑 관계는 다음과 같아요.

  • issuerUrl 파라미터는 --url https://dev-kt-aa9ne.us.auth0.com에 매핑돼요.
  • privateKey 파라미터는 최소 client_idclient_secret 필드를 포함해야 해요.
  • audience 파라미터는 "audience":"https://dev-kt-aa9ne.us.auth0.com/api/v2/"에 매핑돼요. 이 필드는 일부 identity provider에서만 사용돼요.

더 알아보기 (Learn more)