함수에 보안 활성화하기

함수에 보안 활성화하기

함수에서 비밀(secret) 값을 안전하게 다루도록 보안을 활성화하는 방법을 정리해 볼게요. 함수가 비밀 API를 쓰려면 먼저 함수 워커(function worker)에 보안 설정을 켜고, 그 다음 함수 컨텍스트에서 비밀을 꺼내 쓰는 구조예요.

보안 설정은 함수 워커의 SecretsProviderConfigurator로 시작해서 함수 인스턴스의 SecretsProvider로 이어져요. 기본 제공 구현 두 가지를 그대로 쓰거나, 필요하면 나만의 구현을 만들 수도 있어요.

출처: 문서

본문

함수에 보안을 활성화하려면 다음 단계를 완료해요.

사전 준비 (Prerequisites)

  • 함수에 보안을 활성화하려면 먼저 함수 워커에 보안 설정을 활성화해야 해요.

1단계: 함수 워커 구성하기 (Configure function workers)

컨텍스트의 secret API를 사용하려면 함수 워커에 다음 두 매개변수를 설정해야 해요.

  • secretsProviderConfiguratorClassName
  • secretsProviderConfiguratorConfig

Pulsar Functions는 두 가지 SecretsProviderConfigurator 구현을 제공하고, 둘 다 secretsProviderConfiguratorClassName의 값으로 바로 쓸 수 있어요.

  • org.apache.pulsar.functions.secretsproviderconfigurator.DefaultSecretsProviderConfigurator — 시크릿 공급자의 기본(뼈대) 버전으로, ClearTextSecretsProvider를 함수 인스턴스에 연결해요.
  • org.apache.pulsar.functions.secretsproviderconfigurator.KubernetesSecretsProviderConfigurator — Kubernetes에서 실행할 때 기본으로 사용되며, Kubernetes 내장 시크릿을 이용해 (환경 기반 시크릿 공급자, EnvironmentBasedSecretsProvider를 통해) 함수 컨테이너 안에 환경 변수로 바인딩해서 런타임에 함수가 시크릿을 쓸 수 있게 해줘요.

함수 워커는 org.apache.pulsar.functions.secretsproviderconfigurator.SecretsProviderConfigurator 인터페이스를 사용해서, 함수 인스턴스를 시작할 때 SecretsProvider 클래스 이름과 관련 설정을 선택해요.

함수 인스턴스는 org.apache.pulsar.functions.secretsprovider.SecretsProvider 인터페이스를 사용해서 시크릿을 가져와요. SecretsProvider가 사용하는 구현은 SecretsProviderConfigurator가 결정해요.

함수 인스턴스에 다른 SecretsProvider를 쓰고 싶다면 나만의 SecretsProviderConfigurator를 구현할 수도 있어요.

알아두기: Java, Python, Go 런타임에는 다음 두 공급자(provider)가 있어요.

  • ClearTextSecretsProvider (DefaultSecretsProviderConfigurator의 기본값)
  • EnvironmentBasedSecretsProvider (KubernetesSecretsProviderConfigurator의 기본값)

2단계: 시크릿 가져오기 (Get the secret)

SecretsProviderConfigurator를 설정했다면, Context 객체를 사용해서 다음과 같이 시크릿을 가져올 수 있어요.

Java:

import org.apache.pulsar.functions.api.Context;
import org.apache.pulsar.functions.api.Function;
import org.slf4j.Logger;

public class GetSecretValueFunction implements Function<String, Void> {

    @Override
    public Void process(String input, Context context) throws Exception {
        Logger LOG = context.getLogger();
        String secretValue = context.getSecret(input);

        if (!secretValue.isEmpty()) {
            LOG.info("The secret {} has value {}", input, secretValue);
        } else {
            LOG.warn("No secret with key {}", input);
        }

        return null;
    }
}

Python:

from pulsar import Function

class GetSecretValueFunction(Function):
    def process(self, input, context):
        logger = context.get_logger()
        secret_value = context.get_secret(input)
        if secret_provider is None:
            logger.warn('No secret with key {0} '.format(input))
        else:
            logger.info("The secret {0} has value {1}".format(input, secret_value))

Go:

func secretLoggerFunc(ctx context.Context, input []byte) {
    fc, ok := pf.FromContext(ctx)
    if !ok {
        logutil.Fatal("Function context is not defined")
    }

    secretValue := fc.GetSecretValue(string(input))

    if secretValue == nil {
        logutil.Warnf("No secret with key %s", input)
    } else {
        logutil.Infof("The secret %s has value %s", input, secretValue)
    }
}

더 알아보기 (Learn more)

  • 함수 워커 보안 설정 전반은 함수 워커 문서에서 확인해요.
  • Kubernetes에서의 시크릿 관리가 궁금하다면 Kubernetes 런타임 문서를 살펴보세요.
  • 인증·암호화 같은 Pulsar 보안 기능은 Pulsar 보안 문서를 참고해요.