개발 가이드
BioStar X와 연동되는 플러그인의 실제 개발 방법과 구현 예시를 안내합니다.
필수 엔드포인트 구현
BioStar X와 연동되는 플러그인을 개발하려면 다음 두 개의 엔드포인트를 반드시 구현해야 합니다. 이 문서에서는 /bsx
를 예시 경로로 사용합니다.
플러그인 등록 엔드포인트
GET /bsx
플러그인을 등록할 때 BioStar X Service Manager에서 서버 접근성을 확인하기 위해 호출하는 엔드포인트입니다.
요청 형식
GET /bsx
Headers:
X-BioStar-Ping: <ping_token>
구현 요구 사항
Python FastAPI
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/bsx")
async def bsx_ping(request: Request):
"""BioStar X 플러그인 등록용 ping 엔드포인트"""
ping_token = request.headers.get("x-biostar-ping")
# 응답에 ping 토큰 반환
response_data = {"token": ping_token}
response = JSONResponse(content=response_data)
return response
응답 형식
Success (200 OK)
{
"token": "<ping_token_value>"
}
테스트
curl
명령어를 사용해 수동으로 엔드포인트를 테스트할 수 있습니다.
curl -H "X-BioStar-Ping: test123" http://localhost:8000/bsx
사용자 인증 콜백 엔드포인트
POST /bsx
사용자가 BioStar X 웹 인터페이스에서 플러그인 아이콘을 클릭할 때 호출되는 엔드포인트입니다. 이 과정에서 BioStar X에 로그한 사용자의 세션(session)을 요청해 응답을 받습니다.
알아두기
BioStar X와 플러그인 간의 보안 통신을 위해 인증서가 필요합니다. 인증서는 플러그인 등록 후 해당 플러그인 상세 페이지에서 다운로드할 수 있습니다. 자세한 내용은 다음 문서를 참고하세요.
요청 형식
POST /bsx
Content-Type: application/x-www-form-urlencoded
user_id={user_id}&plugin_id={plugin_id}
구현 요구사항
-
매개변수 검증:
user_id
와plugin_id
필수 값 확인 -
AES 키 생성: 보안 통신용 32바이트 키 생성
-
키 암호화: RSA 공개키로 AES 키 암호화(예시 코드에서는
public_key.pem
파일 이름으로 가정) -
세션 브리지 요청: BioStar X 서버에 세션 요청
-
세션 복호화: 받은 암호화된 세션 ID를 AES로 복호화
import uuid
import requests
from fastapi import HTTPException, Form
@app.post("/bsx")
async def bsx_callback(
request: Request,
user_id: str = Form(None, description="사용자 ID"),
plugin_id: str = Form(None, description="플러그인 ID")
):
"""BioStar X 플러그인 콜백 처리"""
# 1. 필수 매개변수 검증
if not user_id:
raise HTTPException(status_code=400, detail="user_id가 필요합니다")
if not plugin_id:
raise HTTPException(status_code=400, detail="plugin_id가 필요합니다")
# 2. 보안 통신을 위한 AES 키 생성
key = uuid.uuid4().hex # 32바이트 키
# 3. RSA 공개키로 키 암호화
encrypted_key = encrypt_with_public_key(key, "public_key.pem")
# 4. BioStar 서버에 세션 브리지 요청
payload = {
"user_id": user_id,
"plugin_id": plugin_id,
"key": encrypted_key
}
response = requests.post(
f"https://{BIOSTAR_SERVER}/api/session/bridge",
json=payload,
verify=False
)
# 5. 응답 처리
if response.status_code == 200:
data = response.json()
if data.get("Response", {}).get("code") == "0":
# 세션 ID 복호화
encrypted_session = data.get("bs_session_id")
bs_session_id = decrypt_aes256_base64(encrypted_session, key)
else:
# BioStar X 오류 처리
error_msg = data.get("Response", {}).get("message", "알 수 없는 오류")
raise HTTPException(status_code=400, detail=f"BioStar X 오류: {error_msg}")
else:
raise HTTPException(status_code=500, detail="BioStar X 서버 연결 실패")
테스트
curl
명령어를 사용해 수동으로 엔드포인트를 테스트할 수 있습니다.
curl -X POST http://localhost:8000/bsx \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user_id={user_id}&plugin_id={your_plugin_id}"
암호화 구현
다음 암호화 함수를 구현해야 합니다.
RSA 공개키 암호화
from cryptography.hazmat.primitives import serialization, padding
import base64
def encrypt_with_public_key(message: str, public_key_path: str) -> str:
"""RSA 공개키로 메시지 암호화"""
with open(public_key_path, 'rb') as key_file:
public_key = serialization.load_pem_public_key(key_file.read())
message_bytes = message.encode('utf-8')
encrypted = public_key.encrypt(message_bytes, padding.PKCS1v15())
return base64.b64encode(encrypted).decode('utf-8')
AES-256 복호화
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64
def decrypt_aes256_base64(encrypted_data: str, key: str) -> str:
"""AES256으로 암호화된 base64 데이터 복호화"""
key_bytes = key.encode('utf-8')
# 32바이트 키 보장
if len(key_bytes) != 32:
if len(key_bytes) < 32:
key_bytes = key_bytes.ljust(32, b'\0')
else:
key_bytes = key_bytes[:32]
cipher_text = base64.b64decode(encrypted_data)
iv = key_bytes[:16] # 첫 16바이트를 IV로 사용
cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(cipher_text), AES.block_size)
return decrypted.decode('utf-8')