Blog
nifisecuritytls

Apache NiFi 2.x 3노드 클러스터 구성 가이드 — TLS 인증서, NiFi Registry, 외부 API 접근

NiFi Toolkit을 활용한 Root CA 생성 및 노드별 인증서 발급, 3노드 클러스터 구성, NiFi Registry TLS 설정, 외부 HTTPS API 호출까지 실무 가이드.

Data Dynamics2026年4月13日27 min read
This post is not yet translated. The original Korean version is shown below.

개요

은행 금고를 상상해 보세요. 금고 문을 열려면 올바른 열쇠가 있어야 하고, 내부 통신도 모두 암호화됩니다. Apache NiFi 2.x가 꼭 그렇습니다 — 기본적으로 HTTPS와 인증을 요구하며, 각 노드에 고유한 TLS 인증서가 있어야 비로소 문이 열립니다.

프로덕션 환경에서 NiFi 클러스터를 구성하려면 각 노드에 고유한 TLS 인증서를 발급하고, 노드 간 통신과 클라이언트 접근을 모두 암호화해야 합니다.

이 글에서 배우는 것

  • NiFi Toolkit으로 Root CA와 노드 인증서를 한 번에 생성하는 방법
  • 3노드 클러스터의 ZooKeeper·nifi.properties·authorizers.xml 설정
  • NiFi Registry를 같은 CA로 묶어 상호 신뢰하도록 구성하는 방법
  • 외부 시스템에서 mTLS·Bearer Token으로 REST API를 호출하는 방법
  • 트러블슈팅 체크리스트로 흔한 오류를 빠르게 해결하는 방법

이 가이드에서는 다음 구성을 다룹니다:

  • 3노드 NiFi 클러스터 (Embedded ZooKeeper)
  • NiFi Toolkit을 사용한 Root CA 및 노드 인증서 생성
  • NiFi Registry TLS 설정
  • 외부 HTTPS API 접근을 위한 클라이언트 인증서 설정

환경 구성

역할호스트명IP
NiFi Node 1 + ZooKeepernifi1.example.com192.168.0.1
NiFi Node 2 + ZooKeepernifi2.example.com192.168.0.2
NiFi Node 3 + ZooKeepernifi3.example.com192.168.0.3
NiFi Registrynifi1.example.com192.168.0.1 (Node 1과 동일)

전제 조건: Java 21 JDK가 모든 노드에 설치되어 있어야 합니다 (NiFi 2.x 요구사항).


1. NiFi Toolkit을 사용한 TLS 인증서 생성

1.1 TLS 인증서 요구사항 (Cloudera CFM 기준)

인증서를 직접 만들기 전에 NiFi가 어떤 인증서를 받아들이는지 먼저 확인해 봅시다. 특히 와일드카드 인증서는 사용할 수 없고, 노드마다 고유한 인증서가 필요하다는 점이 핵심입니다.

항목요구사항
Signature AlgorithmSHA-256 (sha256WithRSAEncryption)
Key Usage (X509v3)Digital Signature, Key Encipherment
Extended Key Usage (X509v3)TLS Web Server Authentication (serverAuth), TLS Web Client Authentication (clientAuth)
Subject Alternative Names (SAN)노드의 FQDN을 DNS 항목으로 포함
KeyStore단일 PrivateKeyEntry만 포함
Wildcard 인증서사용 불가 — 노드별 고유 인증서 필수
Keystore/Key 비밀번호동일하게 설정하거나 둘 다 미설정

1.2 NiFi Toolkit 다운로드

NiFi Toolkit은 Apache NiFi 배포에 포함되어 있습니다. NiFi 2.x와 동일한 버전의 Toolkit을 사용해야 합니다 — 버전이 다르면 인증서 호환성 문제가 생길 수 있으니 주의하세요.

# NiFi Toolkit 다운로드 (NiFi 버전과 동일하게)
wget https://archive.apache.org/dist/nifi/2.4.0/nifi-toolkit-2.4.0-bin.zip
unzip nifi-toolkit-2.4.0-bin.zip
cd nifi-toolkit-2.4.0

1.3 Standalone 모드로 인증서 일괄 생성

여기서 NiFi Toolkit의 진가가 드러납니다. 명령 한 줄로 Root CA 생성부터 노드별 Keystore/Truststore 생성, nifi.properties 업데이트까지 한 번에 처리해 줍니다. 수동으로 하면 며칠 걸릴 작업을 몇 초 만에 해결할 수 있죠.

./bin/tls-toolkit.sh standalone \
  -n 'nifi1.example.com,nifi2.example.com,nifi3.example.com' \
  -C 'CN=admin, OU=NIFI' \
  -o ./certs \
  -K changeit \
  -S changeit \
  -P changeit \
  --days 825 \
  -k 2048

옵션 설명:

옵션설명
-n인증서를 생성할 호스트명 목록 (쉼표 구분)
-C클라이언트 인증서 DN (Initial Admin 또는 API 호출용)
-o인증서 출력 디렉토리
-K개별 키 비밀번호
-SKeystore 비밀번호
-PTruststore 비밀번호
--days인증서 유효기간 (macOS는 825일 이하 권장)
-k키 크기 (2048 bit)

1.4 생성 결과물 확인

명령이 성공적으로 완료되면 ./certs/ 디렉토리 아래에 노드별 폴더와 클라이언트 인증서가 생성됩니다. 아래 구조를 확인해 두면 나중에 파일을 배포할 때 헷갈리지 않습니다.

tree ./certs/
./certs/
├── nifi-cert.pem                    # Root CA 공개 인증서
├── nifi-key.key                     # Root CA 개인 키
├── nifi1.example.com/
│   ├── keystore.jks                 # 노드 1 Keystore
│   ├── truststore.jks               # 노드 1 Truststore (Root CA 포함)
│   └── nifi.properties              # 자동 생성된 TLS 설정
├── nifi2.example.com/
│   ├── keystore.jks
│   ├── truststore.jks
│   └── nifi.properties
├── nifi3.example.com/
│   ├── keystore.jks
│   ├── truststore.jks
│   └── nifi.properties
├── CN=admin_OU=NIFI.p12             # 클라이언트 인증서 (PKCS12)
├── CN=admin_OU=NIFI.password        # 클라이언트 인증서 비밀번호
└── CN=admin_OU=NIFI_config.json     # 클라이언트 인증서 메타정보

핵심 포인트: Toolkit이 생성한 truststore.jks에는 Root CA 인증서가 포함되어 있어, 같은 CA로 서명된 모든 노드의 인증서를 상호 신뢰할 수 있습니다.

1.5 기존 Root CA를 사용하는 경우

조직에 이미 운영 중인 Root CA나 Intermediate CA가 있다면 새로 CA를 만들 필요가 없습니다. --additionalCACertificate 옵션 하나만 추가하면 기존 CA를 재활용할 수 있습니다.

./bin/tls-toolkit.sh standalone \
  -n 'nifi1.example.com,nifi2.example.com,nifi3.example.com' \
  -C 'CN=admin, OU=NIFI' \
  --additionalCACertificate /path/to/existing-ca.pem \
  -o ./certs \
  -K changeit \
  -S changeit \
  -P changeit

1.6 인증서 검증

인증서를 배포하기 전에 반드시 요구사항을 충족하는지 확인하세요. 이 단계를 건너뛰면 나중에 클러스터 기동 후 알 수 없는 오류로 시간을 낭비하는 일이 생깁니다.

# Keystore 내용 확인
keytool -list -v -keystore ./certs/nifi1.example.com/keystore.jks \
  -storepass changeit
 
# SAN, Key Usage, Extended Key Usage 확인
keytool -list -v -keystore ./certs/nifi1.example.com/keystore.jks \
  -storepass changeit | grep -A 5 "SubjectAlternativeName\|ExtendedKeyUsages\|KeyUsage"
 
# Truststore에 Root CA가 포함되어 있는지 확인
keytool -list -keystore ./certs/nifi1.example.com/truststore.jks \
  -storepass changeit

세 가지 항목이 모두 확인되어야 NiFi가 인증서를 정상적으로 인식합니다:

  • SAN에 해당 노드의 FQDN이 DNS 항목으로 포함
  • Extended Key Usage에 serverAuthclientAuth가 모두 포함
  • Key Usage에 DigitalSignatureKey_Encipherment가 포함

2. NiFi 클러스터 구성

2.1 인증서 배포

인증서가 준비됐다면 이제 각 노드로 파일을 배포할 차례입니다. 노드마다 자신의 Keystore와 공유 Truststore를 받아야 합니다 — 다른 노드의 Keystore를 실수로 복사하지 않도록 주의하세요.

# 노드 1 (192.168.0.1)
scp ./certs/nifi1.example.com/keystore.jks  root@192.168.0.1:/opt/nifi/conf/
scp ./certs/nifi1.example.com/truststore.jks root@192.168.0.1:/opt/nifi/conf/
 
# 노드 2 (192.168.0.2)
scp ./certs/nifi2.example.com/keystore.jks  root@192.168.0.2:/opt/nifi/conf/
scp ./certs/nifi2.example.com/truststore.jks root@192.168.0.2:/opt/nifi/conf/
 
# 노드 3 (192.168.0.3)
scp ./certs/nifi3.example.com/keystore.jks  root@192.168.0.3:/opt/nifi/conf/
scp ./certs/nifi3.example.com/truststore.jks root@192.168.0.3:/opt/nifi/conf/

2.2 Sensitive Properties Key 생성

NiFi는 패스워드 같은 민감한 속성을 암호화해서 저장합니다. 클러스터의 모든 노드가 같은 키를 공유해야 서로의 암호화 데이터를 복호화할 수 있습니다.

# 랜덤 키 생성
openssl rand -base64 32
# 출력 예: k8Jh3F7gT2mN9pQr4sVw6xYz1aBcDeF0hIjKlMnOpRs=

중요: 이 키를 안전한 곳에 보관하세요. 분실하면 NiFi가 암호화된 속성을 복호화할 수 없습니다.

2.3 nifi.properties 설정

이제 NiFi가 HTTPS로만 응답하고, 클러스터 노드끼리 안전하게 통신하도록 설정합니다. 대부분의 값은 모든 노드에서 동일하고, {NODE_HOSTNAME} 부분만 노드마다 다르게 지정하면 됩니다.

공통 설정 (모든 노드 동일)

# ==================== Web Properties ====================
# HTTP를 비활성화하고 HTTPS만 사용
nifi.web.http.host=
nifi.web.http.port=
nifi.web.https.host={NODE_HOSTNAME}
nifi.web.https.port=8443
 
# ==================== Security Properties ====================
nifi.security.keystore=./conf/keystore.jks
nifi.security.keystoreType=jks
nifi.security.keystorePasswd=changeit
nifi.security.keyPasswd=changeit
nifi.security.truststore=./conf/truststore.jks
nifi.security.truststoreType=jks
nifi.security.truststorePasswd=changeit
 
# ==================== Sensitive Properties ====================
# 모든 노드에서 반드시 동일한 값
nifi.sensitive.props.key=k8Jh3F7gT2mN9pQr4sVw6xYz1aBcDeF0hIjKlMnOpRs=
 
# ==================== Cluster Properties ====================
nifi.cluster.is.node=true
nifi.cluster.node.address={NODE_HOSTNAME}
nifi.cluster.node.protocol.port=11443
nifi.cluster.protocol.is.secure=true
 
# ==================== ZooKeeper Properties ====================
nifi.state.management.embedded.zookeeper.start=true
nifi.zookeeper.connect.string=nifi1.example.com:2181,nifi2.example.com:2181,nifi3.example.com:2181
nifi.zookeeper.connect.timeout=10 secs
nifi.zookeeper.session.timeout=10 secs
 
# ==================== Cluster Load Balancing ====================
nifi.cluster.load.balance.host={NODE_HOSTNAME}
nifi.cluster.load.balance.port=6342

노드별 차이 요약

속성Node 1Node 2Node 3
nifi.web.https.hostnifi1.example.comnifi2.example.comnifi3.example.com
nifi.cluster.node.addressnifi1.example.comnifi2.example.comnifi3.example.com
nifi.cluster.load.balance.hostnifi1.example.comnifi2.example.comnifi3.example.com

2.4 Embedded ZooKeeper 설정

NiFi의 Embedded ZooKeeper는 클러스터 내 리더 선출과 상태 동기화를 담당합니다. zookeeper.properties에 3개 노드를 모두 등록하고, 각 노드에 고유한 myid 파일을 만들어 주면 됩니다.

zookeeper.properties

각 노드의 /opt/nifi/conf/zookeeper.properties를 수정합니다.

dataDir=./state/zookeeper
clientPort=2181
initLimit=10
syncLimit=5
tickTime=2000
autopurge.snapRetainCount=30
autopurge.purgeInterval=1
 
server.1=nifi1.example.com:2888:3888
server.2=nifi2.example.com:2888:3888
server.3=nifi3.example.com:2888:3888

myid 파일 생성

각 노드의 ZooKeeper 데이터 디렉토리에 myid 파일을 생성합니다.

# 노드 1 (192.168.0.1)
mkdir -p /opt/nifi/state/zookeeper
echo 1 > /opt/nifi/state/zookeeper/myid
 
# 노드 2 (192.168.0.2)
mkdir -p /opt/nifi/state/zookeeper
echo 2 > /opt/nifi/state/zookeeper/myid
 
# 노드 3 (192.168.0.3)
mkdir -p /opt/nifi/state/zookeeper
echo 3 > /opt/nifi/state/zookeeper/myid

2.5 state-management.xml 설정

각 노드의 /opt/nifi/conf/state-management.xml에서 ZooKeeper 연결 문자열을 수정합니다.

<cluster-provider>
    <id>zk-provider</id>
    <class>org.apache.nifi.controller.state.providers.zookeeper.ZooKeeperStateProvider</class>
    <property name="Connect String">nifi1.example.com:2181,nifi2.example.com:2181,nifi3.example.com:2181</property>
    <property name="Root Node">/nifi</property>
    <property name="Session Timeout">10 seconds</property>
    <property name="Access Control">CreatorOnly</property>
</cluster-provider>

2.6 authorizers.xml 설정

authorizers.xml은 "누가 NiFi에 접근할 수 있는가"를 정의하는 파일입니다. Initial Admin Identity는 Toolkit으로 생성한 클라이언트 인증서의 DN과 정확히 일치해야 합니다 — 공백 한 칸 차이로도 인증 실패가 납니다.

<authorizers>
    <userGroupProvider>
        <identifier>file-user-group-provider</identifier>
        <class>org.apache.nifi.authorization.FileUserGroupProvider</class>
        <property name="Users File">./conf/users.xml</property>
        <property name="Initial User Identity 1">CN=admin, OU=NIFI</property>
        <property name="Initial User Identity 2">CN=nifi1.example.com, OU=NIFI</property>
        <property name="Initial User Identity 3">CN=nifi2.example.com, OU=NIFI</property>
        <property name="Initial User Identity 4">CN=nifi3.example.com, OU=NIFI</property>
    </userGroupProvider>
 
    <accessPolicyProvider>
        <identifier>file-access-policy-provider</identifier>
        <class>org.apache.nifi.authorization.FileAccessPolicyProvider</class>
        <property name="User Group Provider">file-user-group-provider</property>
        <property name="Authorizations File">./conf/authorizations.xml</property>
        <property name="Initial Admin Identity">CN=admin, OU=NIFI</property>
        <property name="Node Identity 1">CN=nifi1.example.com, OU=NIFI</property>
        <property name="Node Identity 2">CN=nifi2.example.com, OU=NIFI</property>
        <property name="Node Identity 3">CN=nifi3.example.com, OU=NIFI</property>
    </accessPolicyProvider>
 
    <authorizer>
        <identifier>managed-authorizer</identifier>
        <class>org.apache.nifi.authorization.StandardManagedAuthorizer</class>
        <property name="Access Policy Provider">file-access-policy-provider</property>
    </authorizer>
</authorizers>

주의: Initial Admin IdentityNode Identity의 DN 형식은 인증서의 DN과 정확히 일치해야 합니다. 공백, 대소문자, 순서까지 동일해야 합니다.

2.7 방화벽 포트 개방

인증서와 설정이 완벽해도 방화벽이 막혀 있으면 클러스터가 뜨지 않습니다. 노드 간 통신에 필요한 6개 포트를 모든 노드에서 열어 두세요.

포트용도
8443NiFi HTTPS Web UI / API
11443NiFi 클러스터 노드 프로토콜
6342NiFi 클러스터 Load Balancing
2181ZooKeeper 클라이언트
2888ZooKeeper 팔로워
3888ZooKeeper 리더 선출
# firewalld 사용 시 (각 노드에서 실행)
firewall-cmd --permanent --add-port=8443/tcp
firewall-cmd --permanent --add-port=11443/tcp
firewall-cmd --permanent --add-port=6342/tcp
firewall-cmd --permanent --add-port=2181/tcp
firewall-cmd --permanent --add-port=2888/tcp
firewall-cmd --permanent --add-port=3888/tcp
firewall-cmd --reload

2.8 /etc/hosts 설정

DNS 서버가 없는 환경이라면 /etc/hosts에 호스트명을 직접 등록해 두세요. TLS 인증서의 SAN에는 FQDN이 들어가 있기 때문에, 호스트명이 제대로 해석되지 않으면 인증서 검증에서 실패합니다.

192.168.0.1  nifi1.example.com  nifi1
192.168.0.2  nifi2.example.com  nifi2
192.168.0.3  nifi3.example.com  nifi3

2.9 클러스터 시작

드디어 NiFi를 띄울 시간입니다. 3개 노드를 가능한 한 동시에 시작해야 ZooKeeper 쿼럼이 빠르게 형성됩니다. 로그를 열어 두고 오류 메시지를 실시간으로 확인하는 것이 좋습니다.

# 각 노드에서 실행
/opt/nifi/bin/nifi.sh start
 
# 로그 확인
tail -f /opt/nifi/logs/nifi-app.log

정상 구동 후 https://nifi1.example.com:8443/nifi 로 접속할 수 있습니다.


3. NiFi Registry TLS 설정

NiFi Registry는 플로우 버전 관리를 담당하는 보조 서비스입니다. NiFi 클러스터와 같은 Root CA로 서명된 인증서를 사용하면, 별도의 신뢰 설정 없이 두 시스템이 서로를 자동으로 인식합니다. Node 1 (192.168.0.1)에 설치하는 것으로 가정합니다.

3.1 NiFi Registry용 인증서 생성

Registry도 동일한 Root CA로 서명된 인증서가 필요합니다. 이미 만들어 둔 CA 파일을 재활용하면 됩니다.

# 기존에 생성한 CA를 재사용하여 Registry 인증서 생성
./bin/tls-toolkit.sh standalone \
  -n 'nifi1.example.com' \
  -o ./certs-registry \
  -K changeit \
  -S changeit \
  -P changeit \
  --nifiDnPrefix 'CN=' \
  --nifiDnSuffix ', OU=NIFI-REGISTRY'

: 이미 생성한 NiFi CA를 재사용하려면 ./certs 디렉토리의 nifi-cert.pemnifi-key.key./certs-registry 디렉토리에 미리 복사해두면, Toolkit이 해당 CA로 서명합니다.

# CA 재사용 방법
mkdir -p ./certs-registry
cp ./certs/nifi-cert.pem ./certs-registry/
cp ./certs/nifi-key.key ./certs-registry/
 
./bin/tls-toolkit.sh standalone \
  -n 'nifi1.example.com' \
  -o ./certs-registry \
  -K changeit \
  -S changeit \
  -P changeit \
  --nifiDnPrefix 'CN=' \
  --nifiDnSuffix ', OU=NIFI-REGISTRY'

3.2 인증서 배포

cp ./certs-registry/nifi1.example.com/keystore.jks  /opt/nifi-registry/conf/keystore.jks
cp ./certs-registry/nifi1.example.com/truststore.jks /opt/nifi-registry/conf/truststore.jks

한 문장으로: 같은 Root CA로 서명된 인증서끼리는 자동으로 서로를 신뢰합니다.

NiFi Registry의 Truststore에는 NiFi 노드들과 동일한 Root CA가 들어 있습니다. 따라서 NiFi 노드 → Registry, Registry → NiFi 노드 방향 모두 추가 설정 없이 상호 신뢰가 성립합니다.

3.3 nifi-registry.properties 설정

/opt/nifi-registry/conf/nifi-registry.properties를 수정합니다.

# ==================== Web Properties ====================
nifi.registry.web.http.host=
nifi.registry.web.http.port=
nifi.registry.web.https.host=nifi1.example.com
nifi.registry.web.https.port=18443
 
# ==================== Security Properties ====================
nifi.registry.security.keystore=./conf/keystore.jks
nifi.registry.security.keystoreType=jks
nifi.registry.security.keystorePasswd=changeit
nifi.registry.security.keyPasswd=changeit
nifi.registry.security.truststore=./conf/truststore.jks
nifi.registry.security.truststoreType=jks
nifi.registry.security.truststorePasswd=changeit
nifi.registry.security.needClientAuth=true
속성설명
nifi.registry.security.needClientAuthtrue이면 클라이언트(NiFi 포함)가 반드시 인증서를 제시해야 함

3.4 NiFi Registry authorizers.xml 설정

NiFi Registry의 /opt/nifi-registry/conf/authorizers.xml에서 NiFi 노드들의 Identity를 등록합니다.

<authorizers>
    <userGroupProvider>
        <identifier>file-user-group-provider</identifier>
        <class>org.apache.nifi.registry.security.authorization.file.FileUserGroupProvider</class>
        <property name="Users File">./conf/users.xml</property>
        <property name="Initial User Identity 1">CN=admin, OU=NIFI</property>
        <property name="Initial User Identity 2">CN=nifi1.example.com, OU=NIFI</property>
        <property name="Initial User Identity 3">CN=nifi2.example.com, OU=NIFI</property>
        <property name="Initial User Identity 4">CN=nifi3.example.com, OU=NIFI</property>
    </userGroupProvider>
 
    <accessPolicyProvider>
        <identifier>file-access-policy-provider</identifier>
        <class>org.apache.nifi.registry.security.authorization.file.FileAccessPolicyProvider</class>
        <property name="User Group Provider">file-user-group-provider</property>
        <property name="Authorizations File">./conf/authorizations.xml</property>
        <property name="Initial Admin Identity">CN=admin, OU=NIFI</property>
        <property name="NiFi Identity 1">CN=nifi1.example.com, OU=NIFI</property>
        <property name="NiFi Identity 2">CN=nifi2.example.com, OU=NIFI</property>
        <property name="NiFi Identity 3">CN=nifi3.example.com, OU=NIFI</property>
    </accessPolicyProvider>
 
    <authorizer>
        <identifier>managed-authorizer</identifier>
        <class>org.apache.nifi.registry.security.authorization.StandardManagedAuthorizer</class>
        <property name="Access Policy Provider">file-access-policy-provider</property>
    </authorizer>
</authorizers>

3.5 NiFi Registry 시작

/opt/nifi-registry/bin/nifi-registry.sh start
tail -f /opt/nifi-registry/logs/nifi-registry-app.log

접속 URL: https://nifi1.example.com:18443/nifi-registry


4. NiFi에서 Registry 연동 설정

TLS 설정이 모두 끝났다면, 이제 NiFi Web UI에서 Registry를 연결해 보겠습니다. 같은 Root CA를 쓰고 있다면 URL만 입력해도 통신이 바로 됩니다.

  1. Controller Settings 접근: 햄버거 메뉴 > Controller Settings > Registry Clients
  2. Registry Client 추가:
    • Name: NiFi Registry
    • URL: https://nifi1.example.com:18443
  3. NiFi가 Registry에 접근할 때 자신의 클라이언트 인증서를 사용하므로, 같은 Root CA 기반이면 추가 설정 없이 통신됩니다.

5. 외부 HTTPS API 접근 설정

NiFi 클러스터가 가동됐다면 외부 시스템에서 REST API로 제어하고 싶어질 겁니다. NiFi 2.x는 인증 없는 HTTP 접근을 허용하지 않으므로, 아래 세 가지 방법 중 하나를 선택해야 합니다.

한 문장으로: 외부 API 호출도 반드시 인증이 필요하며, mTLS 또는 Bearer Token을 사용합니다.

5.1 방법 1: 클라이언트 인증서 (mTLS) 사용

가장 안전한 방법입니다. Toolkit이 자동으로 만들어 준 클라이언트 인증서(CN=admin_OU=NIFI.p12)를 curl, Python, Java 어디서든 활용할 수 있습니다.

curl로 API 호출

# 클라이언트 인증서 비밀번호 확인
cat ./certs/CN=admin_OU=NIFI.password
 
# PKCS12 인증서를 사용한 API 호출
curl -k --cert-type P12 \
  --cert ./certs/CN=admin_OU=NIFI.p12:<CLIENT_PASSWORD> \
  https://nifi1.example.com:8443/nifi-api/flow/status

Python으로 API 호출

Python의 requests 라이브러리는 PKCS12를 직접 읽지 못하므로 먼저 PEM 형식으로 변환해야 합니다.

# PKCS12를 PEM으로 변환 (인증서 + 키 분리)
openssl pkcs12 -in ./certs/CN=admin_OU=NIFI.p12 \
  -clcerts -nokeys -out client-cert.pem \
  -passin pass:<CLIENT_PASSWORD>
 
openssl pkcs12 -in ./certs/CN=admin_OU=NIFI.p12 \
  -nocerts -nodes -out client-key.pem \
  -passin pass:<CLIENT_PASSWORD>
import requests
 
response = requests.get(
    'https://nifi1.example.com:8443/nifi-api/flow/status',
    cert=('client-cert.pem', 'client-key.pem'),
    verify='./certs/nifi-cert.pem'  # Root CA 인증서로 서버 검증
)
print(response.json())

Java로 API 호출

import javax.net.ssl.*;
import java.io.FileInputStream;
import java.net.http.*;
import java.net.URI;
import java.security.KeyStore;
 
// Keystore 로드 (클라이언트 인증서)
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("CN=admin_OU=NIFI.p12"),
    "<CLIENT_PASSWORD>".toCharArray());
 
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore, "<CLIENT_PASSWORD>".toCharArray());
 
// Truststore 로드 (Root CA)
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("truststore.jks"),
    "changeit".toCharArray());
 
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(trustStore);
 
// SSL Context 구성
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
 
// HTTP 클라이언트로 API 호출
HttpClient client = HttpClient.newBuilder()
    .sslContext(sslContext)
    .build();
 
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://nifi1.example.com:8443/nifi-api/flow/status"))
    .GET()
    .build();
 
HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

5.2 방법 2: Bearer Token (JWT) 사용

인증서 관리가 번거롭다면 토큰 방식을 사용해도 됩니다. Username/Password로 한 번 로그인하고 받은 JWT 토큰을 이후 모든 요청에 재사용하는 방식입니다. Single User 인증 또는 LDAP 인증이 설정된 경우에 사용할 수 있습니다.

# 토큰 발급
TOKEN=$(curl -k -X POST \
  https://nifi1.example.com:8443/nifi-api/access/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'username=admin&password=your_password')
 
# 토큰을 사용한 API 호출
curl -k -H "Authorization: Bearer $TOKEN" \
  https://nifi1.example.com:8443/nifi-api/flow/status

참고: -k 옵션은 자체 서명된 인증서를 사용할 때 인증서 검증을 건너뜁니다. 프로덕션에서는 --cacert 옵션으로 Root CA를 지정하세요.

5.3 방법 3: 추가 클라이언트 인증서 생성

모니터링 도구, CI/CD 파이프라인 등 시스템마다 별도의 클라이언트 인증서를 발급하면 접근 권한을 세밀하게 제어할 수 있습니다. 누가 어떤 작업을 했는지 감사 로그에도 명확하게 남습니다.

# 추가 클라이언트 인증서 생성
./bin/tls-toolkit.sh standalone \
  -n 'nifi1.example.com' \
  -C 'CN=monitoring-system, OU=OPERATIONS' \
  -C 'CN=cicd-pipeline, OU=DEVOPS' \
  -o ./certs-clients \
  -K changeit \
  -S changeit \
  -P changeit

생성 후 NiFi의 authorizers.xml에 해당 DN을 추가하고, 적절한 권한을 부여합니다.

<!-- authorizers.xml에 추가 -->
<property name="Initial User Identity 5">CN=monitoring-system, OU=OPERATIONS</property>
<property name="Initial User Identity 6">CN=cicd-pipeline, OU=DEVOPS</property>

주의: Initial User Identity는 NiFi 최초 기동 시에만 적용됩니다. 이미 users.xmlauthorizations.xml이 생성된 상태라면, 해당 파일을 삭제하고 재시작하거나 Web UI에서 직접 사용자를 추가해야 합니다.

5.4 주요 NiFi REST API 엔드포인트

인증이 완료됐다면 아래 엔드포인트로 클러스터 상태 조회부터 시작해 보세요.

엔드포인트메서드설명
/nifi-api/flow/statusGET클러스터 전체 상태
/nifi-api/flow/cluster/summaryGET클러스터 요약 정보
/nifi-api/controller/clusterGET클러스터 노드 목록
/nifi-api/system-diagnosticsGET시스템 진단 정보
/nifi-api/flow/process-groups/rootGET루트 프로세스 그룹 정보
/nifi-api/access/configGET접근 설정 (인증 불필요)

6. 트러블슈팅

NiFi TLS 설정에서 가장 많이 마주치는 오류들을 모았습니다. 에러 메시지를 보고 해당 항목을 찾아 체크해 보세요.

PKIX path building failed

Truststore에 Root CA가 없거나 인증서 체인이 불완전한 경우 발생합니다. 아래 명령으로 Truststore 내용을 확인해 보세요.

# Truststore 내용 확인
keytool -list -keystore truststore.jks -storepass changeit

No subject alternative names present

인증서의 SAN(Subject Alternative Name)에 호스트명이 포함되지 않은 경우 발생합니다.

# SAN 확인
keytool -list -v -keystore keystore.jks -storepass changeit | grep -A 3 "SubjectAlternativeName"

Certificate does not conform to algorithm constraints

인증서의 키 크기가 너무 작은 경우(1024 bit 이하) 발생합니다.

Unable to communicate with node

노드 간 통신이 불가능한 경우 방화벽 포트를 확인합니다.

# 방화벽 포트 확인
nc -zv nifi2.example.com 11443

ZooKeeper 연결 실패

ZooKeeper에 연결할 수 없는 경우 myid 파일과 포트를 확인합니다.

# myid 파일 확인
cat /opt/nifi/state/zookeeper/myid
 
# ZooKeeper 포트 확인
nc -zv nifi1.example.com 2181

authorizers.xml DN 불일치

# 인증서의 정확한 DN 확인
keytool -list -v -keystore keystore.jks -storepass changeit | grep "Owner:"
 
# 출력 예: Owner: CN=nifi1.example.com, OU=NIFI
# → authorizers.xml의 Node Identity와 정확히 일치해야 함

7. 체크리스트

모든 설정을 마쳤다면 아래 항목을 하나씩 점검하세요. 하나라도 빠지면 클러스터가 예상대로 동작하지 않을 수 있습니다.

  • 모든 노드에 Java 21 JDK 설치
  • TLS Toolkit으로 Root CA 및 노드 인증서 생성
  • 인증서의 SAN, Key Usage, Extended Key Usage 요구사항 충족
  • 각 노드에 Keystore/Truststore 배포
  • nifi.sensitive.props.key가 모든 노드에서 동일
  • nifi.properties TLS 및 클러스터 설정 완료
  • zookeeper.properties에 3노드 설정 및 myid 파일 생성
  • state-management.xml ZooKeeper 연결 문자열 설정
  • authorizers.xml Initial Admin Identity 및 Node Identity 설정
  • 방화벽 포트 개방 (8443, 11443, 6342, 2181, 2888, 3888)
  • /etc/hosts 또는 DNS에 호스트명 등록
  • NiFi Registry TLS 설정 및 시작
  • 클라이언트 인증서로 HTTPS API 접근 확인

마치며 — 핵심 요약

  • NiFi Toolkit 하나로 Root CA + 노드 인증서 + Truststore를 일괄 생성할 수 있습니다. 수동 작업은 최대한 피하세요.
  • 같은 Root CA로 서명된 인증서끼리는 자동으로 상호 신뢰됩니다. NiFi ↔ Registry 연동도 이 원칙이 적용됩니다.
  • authorizers.xml의 DN은 인증서 DN과 공백·대소문자·순서까지 정확히 일치해야 합니다. 불일치는 가장 흔한 실수입니다.
  • 외부 API 호출은 mTLS 또는 Bearer Token 중 환경에 맞는 방법을 선택하세요.
  • 클러스터 재구성 시 users.xmlauthorizations.xml을 삭제하고 재시작하면 Initial Admin Identity가 재적용됩니다.
  • 문제가 생기면 트러블슈팅 섹션의 에러 메시지별 체크 순서를 따라가면 대부분 해결됩니다.

이 가이드를 따라 한 번 구성해 두면, 다음 번엔 훨씬 빠르게 클러스터를 세울 수 있을 겁니다. 궁금한 점은 언제든 문의해 주세요.


참고 자료


NiFi Cluster 설정에 대해 도움이 필요하시면 언제든 문의해 주세요.

— Data Dynamics 엔지니어링 팀