Hyperledger Fabric을 구성하는 Orderer와 Peer는 msp
와 tls
키를 갖고 있다. 이 키들은 cryptogen
을 이용하여 키를 생성하거나, Fabric CA 서버에 enroll
하여 얻을 수 있다. cryptogen
을 이용하여 생성하면, 인증서 만료 값이 매우 길기 때문에(10년인가 15년인가로 알고 있다) 걱정할 필요가 없지만, Fabric CA의 경우 fabric-ca-server-config.yaml
파일을 수정하지 않는한 기본 1년으로 설정되어 있다. 그렇기 때문에 네트워크가 중단되는 사태를 맞지 않으려면, 1년마다 반드시 갱신을 해주어야 한다.
참고로, msp
는 만료가 되어도 네트워크가 정상 작동한다. 하지만 msp
가 만료된 Orderer 또는 Peer 프로세스를 중단시키면, 다시 실행시킬 수 없다. 즉, msp
가 만료되어도 최소한의 데이터 백업 등을 위해 네트워크에서 바로 퇴출시키지 않고 유예시켜주는 것이다. 반면에 tls
는 만료되는 순간 즉각 퇴출된다. tls
는 말 그대로 TLS 통신을 위한 것이기 때문에, 인증서가 만료되면 애초에 Orderer와 Peer들 사이에 통신이 불가능해진다.
Hyperledger Fabric의 키를 갱신하는 과정은 다음과 같다.
위의 과정은 내가 StackOverflow에 올린 질문글에 yacovm님이 달아주신 댓글을 통해 알게 되었다.
참고로 아래의 모든 과정은 Fabric CA 1.4.4 버전, Hyperledger Fabric 2.2 버전에서 진행했다.
당연하지만, 우선 새로운 키가 필요하다. 키를 새로 발급 받는 방법은 처음에 Fabric CA로부터 msp
와 tls
를 받을 때 했던 방법 그대로 수행하면 된다. reenroll
을 굳이 안 써도 되고, 그냥 마치 처음 하는 것처럼 enroll
을 통해 받으면 된다. register
는 (당연한 말이지만) 할 필요 없다. 처음에 등록한 노드 ID, 비밀번호를 이용하여 enroll
만 다시 받으면 된다. 새로운 키를 받았다면, 어디 한 구석에 잘 저장해두자.
Orderer의 키를 갱신하는 건 복잡하고, 사실 이게 핵심이다. 단순히 Orderer의 키를 바꿔칠 뿐 아니라, Channel의 Configuration 값을 수정해야하기 때문이다.
Hyperledger Fabric의 Channel 블록에는 해당 Channel에 참여하는 Orderer들의 노드 ID, tls/signcerts
값을 저장하고 있다. tls/signcerts
값은 우리가 갱신해야 하는 값에 해당하기 때문에, Channel Config Update 절차를 통해, 해당 값을 갱신해주어야 한다.
Channel Config Update 절차는 공식 문서에 잘 정리가 되어 있다. 해당 내용을 요약하면 대충 다음과 같다.
peer channel update
명령어를 통해 Orderer에게 전송한다.2~4번 과정은 configtxlator
를 통해 proto-buf
형태의 Channel Config 파일을 json으로 변경하고, 이걸 다시 proto-buf
파일로 인코딩하는 과정들의 반복으로 구성되어 있다. 또한 jq
가 있으면 꽤 편하니, 미리 준비하도록 하자.
공식 문서를 참고하여 진행하다보면, 이제 json 파일을 수정해야 하는 단계에 올 것이다. 공식 문서의 "Step 2: Modify the config" 단계에 왔다면, 이제 내용을 수정해야 하는데 주의해야 할 점이 있다.
우선 수정해야 할 내용은 channel_group.groups.Orderer.values.ConsensusType.value.metadata.consenters
에 있다. 여기 보면 Orderer 들이 배열로 정의되어 있는데,client_tls_cert
와 server_tls_cert
값을 수정하면 된다. 참고로, channel_group.groups.Orderer.values.ConsensusType.value
위치의 BatchSize
, BatchTimeout
등도 변경 가능한 값들이니 알아두도록 하자.
client_tls_cert
와 server_tls_cert
값은 tls/signcerts
폴더의 인증서 값을 넣으면 되는데, client_tls_cert
와 server_tls_cert
모두 같은 값을 넣으면 된다. 다만, 해당 인증서를 base64로 인코딩해야 하는데, 방법은 다음과 같다.
base64 tls/signcerts/cert.pem | sed ':a;N;$!ba;s/\n//g'
이를 통해 얻은 값을 client_tls_cert
와 server_tls_cert
에 붙여넣고, 저장한 후 나머지 과정을 진행하면 된다. 위의 base64 내용은 yacovm 님이 안내해주신 GitHub 저장소에서 알 수 있었다.
peer channel update
를 통해 Channel Config 가 잘 업데이트 되면, 이제 키 값을 갱신한 Orderer에 새로운 msp
, tls
값을 준다. 보통은 그냥 해당 폴더를 교체하고, Orderer 프로세스(보통 도커 컨테이너)를 재시작해주면 된다.
RAFT 에서는 적어도 3개의 Orderer를 쓰는데, 이를 한번에 업데이트 하면 절대 안된다. 그렇게 되면, 모두가 서로를 알아보지 못하는 데드록에 빠질 수 있다. 그래서 1개의 Orderer에 대해 위의 과정을 모두 완료한 후, 다음 Orderer에 대해 Channel Config fetch부터 전부 다시 진행해주어야 한다. 그렇게 순차적으로 진행해야 Orderer들이 서로를 인식할 수 있게 된다. 그렇기 때문에 RAFT 에서는 위의 과정을 적어도 3번 반복해야 한다.
Peer 키 갱신은 상대적으로 쉽다. 그저 msp
와 tls
폴더를 새로운 키로 교체한 후 프로세스 또는 도커 컨테이너를 재시작해주면 된다.
이게 사실 문제다. 나 같은 경우, 처음으로 인증서 만료에 직면했던 Fabric 체인은 이미 키가 만료된 상태였다. 갑자기 Fabric 네트워크가 동작을 안해서 가보니 이미 인증서가 만료되어 버린 것... 이때는 완전 맨붕에 빠져서 결국 새 네트워크를 띄우고 모든 블록체인 내용을 옮긴 후 기존 것을 버렸었다. 내용은 살렸지만, 그간 내역이 모두 날라가서 어찌보면 블록체인의 의미를 상실한 것이 되어버렸다. 그래서 같은 경우를 겪지 않기 위해, StackOverflow 와 Hyperledger Chat 커뮤니티를 통해 조사한 결과 위의 절차를 알게 되었던 것이다.
위의 모든 과정에서 "키가 이미 만료된 경우"는 Orderer에 대해 다음 몇가지 설정을 추가해서 Orderer를 재시작해주어야 한다.
General.Cluster.TLSHandshakeTimeShift
설정General.Authentication.NoExpirationChecks
설정그리고 Peer 가 Orderer에게 Channel Update 트랜잭션을 보낼 때 --tlsHandshakeTimeShift
옵션을 함께 설정해주어야 한다.
TLSHandshakeTimeShift
의 경우, 해당 시간만큼 tls
인증서의 만료 기간을 연장하는 것을 말한다. 그래서 가령 만료된지 2일이 지났다면, TLSHandshakeTimeShift
값은 적어도 48h
이상이 되어야 한다.
NoExpirationChecks
의 경우, Orderer가 msp
에 대해 만료 체크를 하지 않는 것을 말한다 (공식문서).
이 경우에 대한 논의는 Hyperledger의 공식 JIRA의 이슈에 자세히 나와있으니 참고하자.