diff --git a/app/extensions/k8s/client.py b/app/extensions/k8s/client.py index 3ce0123..b05b0b1 100644 --- a/app/extensions/k8s/client.py +++ b/app/extensions/k8s/client.py @@ -75,7 +75,10 @@ def create_challenge_resource(self, challenge_id, username, namespace="default") # 이미 실행 중인 Challenge가 있으면 데이터베이스에 저장된 포트 번호 반환 if user_challenge.status == 'Running': return user_challenge.port - + + # 공백의 경우 하이픈으로 변환 + challenge_definition = self._normalize_k8s_name(challenge_definition) + # Challenge manifest 생성 challenge_manifest = { "apiVersion": "apps.hexactf.io/v1alpha1", @@ -129,7 +132,36 @@ def create_challenge_resource(self, challenge_id, username, namespace="default") return endpoint - + def _normalize_k8s_name(name: str) -> str: + """ + Kubernetes 리소스 이름을 유효한 형식으로 변환 (소문자 + 공백을 하이픈으로 변경) + + Args: + name (str): 원본 이름 + + Returns: + str: 변환된 Kubernetes 리소스 이름 + """ + if not name or len(name) > 253: + raise ValueError("이름이 비어있거나 길이가 253자를 초과함") + + # 1. 소문자로 변환 + name = name.lower() + + # 2. 공백 및 비허용 문자 (`[^a-z0-9-]`)를 `-`로 변환 + name = re.sub(r'[^a-z0-9-]+', '-', name) + + # 3. 하이픈(-)이 연속적으로 나오면 하나로 줄이기 + name = re.sub(r'-+', '-', name) + + # 4. 앞뒤의 하이픈 제거 + name = name.strip('-') + + # 5. 최종 길이 검사 (1~253자) + if not name or len(name) > 253: + raise ValueError(f"변환 후에도 유효하지 않은 Kubernetes 리소스 이름: {name}") + + return name def _is_valid_k8s_name(self, name: str) -> bool: """ @@ -141,6 +173,10 @@ def _is_valid_k8s_name(self, name: str) -> bool: Returns: bool: 유효한 이름인지 여부 """ + + # 소문자로 변환 + name = name.lower() + # Kubernetes naming convention 검사 if not name or len(name) > 253: return False @@ -164,6 +200,7 @@ def delete_userchallenge(self, username, challenge_id, namespace="default"): """ # UserChallenge 조회 + username = username.lower() # 소문자로 변환 challenge_name = f"challenge-{challenge_id}-{username}" user_challenge_repo = UserChallengesRepository() user_challenge = user_challenge_repo.get_by_user_challenge_name(challenge_name)