Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package DGU_AI_LAB.admin_be.domain.groups.entity;

import DGU_AI_LAB.admin_be.domain.requests.entity.RequestGroup; // 임포트 추가
import DGU_AI_LAB.admin_be.domain.usedIds.entity.UsedId;
import DGU_AI_LAB.admin_be.domain.requests.entity.RequestGroup;
import jakarta.persistence.*;
import lombok.*;

Expand All @@ -26,10 +25,6 @@ public class Group {
@Column(name = "ubuntu_gid", unique = true, nullable = false)
private Long ubuntuGid;

Comment on lines 25 to 27
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ubuntu_gid", referencedColumnName = "id_value", insertable = false, updatable = false)
private UsedId usedId;

@OneToMany(mappedBy = "group", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<RequestGroup> requestGroups = new HashSet<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import DGU_AI_LAB.admin_be.domain.groups.entity.Group;
import DGU_AI_LAB.admin_be.domain.groups.repository.GroupRepository;
import DGU_AI_LAB.admin_be.domain.requests.repository.RequestRepository;
import DGU_AI_LAB.admin_be.domain.usedIds.entity.UsedId;
import DGU_AI_LAB.admin_be.domain.usedIds.repository.UsedIdRepository;
import DGU_AI_LAB.admin_be.domain.usedIds.service.IdAllocationService;
import DGU_AI_LAB.admin_be.error.ErrorCode;
import DGU_AI_LAB.admin_be.error.exception.BusinessException;
Expand All @@ -32,7 +30,6 @@
public class GroupService {

private final GroupRepository groupRepository;
private final UsedIdRepository usedIdRepository;
private final RequestRepository requestRepository;
private final IdAllocationService idAllocationService;
private final @Qualifier("configWebClient") WebClient groupCreationWebClient;
Expand Down Expand Up @@ -141,9 +138,6 @@ public GroupResponseDTO createGroup(CreateGroupRequestDTO dto, Long userId) {
}

// 5. API 호출이 성공한 후에만 로컬 DB에 그룹을 저장합니다.
UsedId usedId = usedIdRepository.findById(assignedGid)
.orElseGet(() -> usedIdRepository.saveAndFlush(UsedId.builder().idValue(assignedGid).build()));

Group group = Group.builder()
.groupName(dto.groupName())
.ubuntuGid(assignedGid)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
public record UserCreationRequestDTO(
@JsonProperty("name")
String username,
int uid,
int gid,
@JsonProperty("passwd_sha512")
String passwordSha512,
@JsonProperty("passwd_base64")
String passwordBase64,
String gecos,
@JsonProperty("primary_group_name")
String primaryGroupName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ public record AcceptInfoResponseDTO(
String username,
@Schema(description = "컨테이너 이미지 (이름:버전)", example = "cuda:11.8")
String image,
@Schema(description = "Ubuntu UID", example = "10001")
Long uid,
@Schema(description = "Ubuntu GID 목록", example = "[1005, 1006]")
List<Long> gid,
@Schema(description = "볼륨 크기 (GiB)", example = "20")
Expand Down Expand Up @@ -78,7 +76,6 @@ public static AcceptInfoResponseDTO fromEntity(Request request, List<Node> nodes
return AcceptInfoResponseDTO.builder()
.username(request.getUbuntuUsername())
.image(image.getImageName() + ":" + image.getImageVersion())
.uid(request.getUbuntuUid().getIdValue())
.gid(
request.getRequestGroups().stream()
.map(rg -> rg.getGroup().getUbuntuGid())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ public record ContainerInfoDTO(
String userName,
@Schema(description = "Ubuntu 사용자명", example = "test2014")
String ubuntuUsername,
@Schema(description = "Ubuntu UID", example = "10001")
Long ubuntuUid,
@Schema(description = "Ubuntu GID 목록", example = "[1005, 1006]")
List<Long> ubuntuGids,
@Schema(description = "리소스 그룹 ID", example = "1")
Expand All @@ -34,7 +32,6 @@ public static ContainerInfoDTO fromEntity(Request request) {
.userId(request.getUser().getUserId())
.userName(request.getUser().getName())
.ubuntuUsername(request.getUbuntuUsername())
//.ubuntuUid(request.getUbuntuUid())
.ubuntuGids(
request.getRequestGroups().stream()
.map(rg -> rg.getGroup().getUbuntuGid())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ public record SaveRequestResponseDTO(
String imageVersion,
@Schema(description = "Ubuntu 사용자명", example = "test2014")
String ubuntuUsername,
@Schema(description = "Ubuntu UID", example = "10001", nullable = true)
Long ubuntuUid,
@Schema(description = "Ubuntu GID 목록", example = "[1005, 1006]")
List<Long> ubuntuGids,
@Schema(description = "볼륨 크기 (GiB)", example = "20")
Expand Down Expand Up @@ -131,9 +129,6 @@ public static SaveRequestResponseDTO fromEntity(Request request) {
.imageName(request.getContainerImage().getImageName())
.imageVersion(request.getContainerImage().getImageVersion())
.ubuntuUsername(request.getUbuntuUsername())
.ubuntuUid(request.getUbuntuUid() != null
? request.getUbuntuUid().getIdValue()
: null)
.ubuntuGids(
request.getRequestGroups().stream()
.map(rg -> rg.getGroup().getUbuntuGid())
Expand Down Expand Up @@ -172,9 +167,6 @@ public static SaveRequestResponseDTO fromEntityWithPortMappings(Request request,
.imageName(request.getContainerImage().getImageName())
.imageVersion(request.getContainerImage().getImageVersion())
.ubuntuUsername(request.getUbuntuUsername())
.ubuntuUid(request.getUbuntuUid() != null
? request.getUbuntuUid().getIdValue()
: null)
.ubuntuGids(
request.getRequestGroups().stream()
.map(rg -> rg.getGroup().getUbuntuGid())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import DGU_AI_LAB.admin_be.domain.containerImage.entity.ContainerImage;
import DGU_AI_LAB.admin_be.domain.groups.entity.Group;
import DGU_AI_LAB.admin_be.domain.resourceGroups.entity.ResourceGroup;
import DGU_AI_LAB.admin_be.domain.usedIds.entity.UsedId;
import DGU_AI_LAB.admin_be.domain.users.entity.User;
import DGU_AI_LAB.admin_be.error.ErrorCode;
import DGU_AI_LAB.admin_be.error.exception.BusinessException;
Expand Down Expand Up @@ -65,10 +64,6 @@ public class Request extends BaseTimeEntity {
@JoinColumn(name = "user_id", nullable = false)
private User user;

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
@JoinColumn(name = "ubuntuUid", referencedColumnName = "id_value", nullable = true)
private UsedId ubuntuUid;

@Column(name = "pod_name", length = 255)
private String podName;

Expand Down Expand Up @@ -166,10 +161,6 @@ public void update(Long newVolumeSizeGiB, LocalDateTime newExpiresAt, String rea

}

public void assignUbuntuUid(UsedId uid) {
this.ubuntuUid = uid;
}

public void assignPodInfo(String podName, String nodeName) {
this.podName = podName;
this.nodeName = nodeName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ public interface RequestRepository extends JpaRepository<Request, Long> {
List<Request> findAllByStatus(Status status);
Optional<Request> findByUbuntuUsernameAndUbuntuPassword(String username, String passwordBase64);
List<Request> findByUserUserIdAndStatus(Long userId, Status status);
Optional<Request> findTopByUbuntuUsernameAndUbuntuUidIsNotNullOrderByApprovedAtDesc(String ubuntuUsername);
boolean existsByUbuntuUsername(String ubuntuUsername);
List<Request> findAllByUser_UserIdAndStatus(Long userId, Status status);
boolean existsByUbuntuUsernameAndUser_UserId(String ubuntuUsername, Long userId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import DGU_AI_LAB.admin_be.domain.requests.repository.RequestRepository;
import DGU_AI_LAB.admin_be.domain.resourceGroups.entity.ResourceGroup;
import DGU_AI_LAB.admin_be.domain.resourceGroups.repository.ResourceGroupRepository;
import DGU_AI_LAB.admin_be.domain.usedIds.service.IdAllocationService;
import DGU_AI_LAB.admin_be.domain.users.entity.User;
import DGU_AI_LAB.admin_be.domain.users.repository.UserRepository;
import DGU_AI_LAB.admin_be.error.ErrorCode;
Expand Down Expand Up @@ -52,7 +51,6 @@ public class AdminRequestCommandService {
private final UserRepository userRepository;
private final ContainerImageRepository containerImageRepository;
private final ResourceGroupRepository resourceGroupRepository;
private final IdAllocationService idAllocationService;
private final ChangeRequestRepository changeRequestRepository;
private final GroupRepository groupRepository;
private final PodExternalPortRepository podExternalPortRepository;
Expand Down Expand Up @@ -100,17 +98,13 @@ public SaveRequestResponseDTO approveRequest(ApproveRequestDTO dto) {
if (request.getStatus() != Status.PENDING) {
throw new BusinessException(ErrorCode.INVALID_REQUEST_STATUS);
}
var allocation = idAllocationService.allocateFor(request);

// 1. 사용자 생성 API 호출
UserCreationRequestDTO userCreationDto = new UserCreationRequestDTO(
request.getUbuntuUsername(),
allocation.getUid().getIdValue().intValue(),
allocation.getPrimaryGroup().getUbuntuGid().intValue(),
request.getUbuntuPassword(),
request.getUser().getName(),
Comment on lines 102 to 105
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Request entity definition =="
fd 'Request.java' src/main -x sed -n '1,260p' {}

echo
echo "== Producers/consumers of ubuntuPassword / passwd_base64 =="
rg -n -C3 --type=java 'ubuntuPassword|passwd_base64|passwd_sha512|passwordBase64' src/main src/test

Repository: CSID-DGU/admin_be

Length of output: 26602


🏁 Script executed:

fd 'AdminRequestCommandService.java' src/main -x cat -n {}

Repository: CSID-DGU/admin_be

Length of output: 14874


passwd_base64 필드에 SHA-512 해시가 전달되고 있습니다. 이는 심각한 계약 위반입니다.

Line 104에서 request.getUbuntuPassword()UserCreationRequestDTOpasswordBase64 필드로 전달하고 있습니다. 그러나 Request.ubuntuPassword는 저장 시점(RequestCommandService 라인 181)에서 이미 PasswordUtil.encodePassword()로 SHA-512 해싱되어 있습니다. 따라서 현재 request.getUbuntuPassword()는 base64 형식이 아닌 SHA-512 16진수 해시입니다. Config-server의 사용자 생성 API는 base64 형식의 패스워드를 기대하므로, 이 변경으로 인해 사용자 생성이 실패하거나 잘못된 패스워드 형식으로 생성될 것입니다.

원본 요청 생성 흐름에서 base64 패스워드를 별도로 저장하거나, 승인 흐름에서 해시 전 원본 패스워드를 별도 소스에서 가져오는 방식으로 수정해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/DGU_AI_LAB/admin_be/domain/requests/service/AdminRequestCommandService.java`
around lines 102 - 105, The code is passing a SHA-512 hex hash into
UserCreationRequestDTO.passwordBase64 via request.getUbuntuPassword(), but
Request.ubuntuPassword is already hashed in RequestCommandService using
PasswordUtil.encodePassword(); fix by supplying the original base64 password
that the config-server expects instead of the hashed value — either: (A) change
the Request model to store the original base64 password (e.g.,
ubuntuPasswordBase64) at creation time in RequestCommandService before calling
PasswordUtil.encodePassword(), and use request.getUbuntuPasswordBase64() when
constructing UserCreationRequestDTO in AdminRequestCommandService, or (B)
retrieve the original base64 credential from the secure source where it was kept
at creation/approval and pass that into UserCreationRequestDTO; update
references to PasswordUtil.encodePassword(), Request.ubuntuPassword, and
UserCreationRequestDTO(passwordBase64) accordingly.

allocation.getPrimaryGroup().getGroupName(),
false // sudo 권한은 기본값으로 false를 설정
request.getUbuntuUsername(), // primary_group_name = username (Linux 관례)
false
Comment on lines 102 to +107
);

try {
Expand Down Expand Up @@ -152,12 +146,6 @@ public SaveRequestResponseDTO approveRequest(ApproveRequestDTO dto) {
CreatePodResponseDTO podResponse = podService.createPod(request.getUbuntuUsername());

// 4. API 호출이 모두 성공한 후에 DB 업데이트
request.assignUbuntuUid(allocation.getUid());
boolean alreadyLinked = request.getRequestGroups().stream()
.anyMatch(rg -> rg.getGroup().getUbuntuGid().equals(allocation.getPrimaryGroup().getUbuntuGid()));
if (!alreadyLinked) {
request.addGroup(allocation.getPrimaryGroup());
}
ContainerImage image = containerImageRepository.findById(dto.imageId())
.orElseThrow(() -> new BusinessException(ErrorCode.RESOURCE_NOT_FOUND));
ResourceGroup rg = resourceGroupRepository.findById(dto.resourceGroupId())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import DGU_AI_LAB.admin_be.domain.requests.entity.Request;
import DGU_AI_LAB.admin_be.domain.requests.entity.Status;
import DGU_AI_LAB.admin_be.domain.requests.repository.RequestRepository;
import DGU_AI_LAB.admin_be.domain.usedIds.entity.UsedId;
import DGU_AI_LAB.admin_be.domain.usedIds.service.IdAllocationService;
import DGU_AI_LAB.admin_be.domain.users.entity.User;
import DGU_AI_LAB.admin_be.error.ErrorCode;
import DGU_AI_LAB.admin_be.error.exception.EntityNotFoundException;
Expand All @@ -22,7 +20,6 @@ public class RequestExpiryService {

private final RequestRepository requestRepository;
private final UbuntuAccountService ubuntuAccountService;
private final IdAllocationService idAllocationService;
private final ApplicationEventPublisher eventPublisher;

@Transactional
Expand All @@ -36,11 +33,6 @@ public void deleteExpiredRequest(Long requestId) {
String ubuntuUsername = request.getUbuntuUsername();
User user = request.getUser();

UsedId usedId = request.getUbuntuUid();
if (usedId != null) {
request.assignUbuntuUid(null);
idAllocationService.releaseId(usedId);
}
ubuntuAccountService.deleteUbuntuAccount(ubuntuUsername);

request.delete();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package DGU_AI_LAB.admin_be.domain.usedIds.entity;

public enum CounterKey {
UID,
SHARED_GID;
}

This file was deleted.

This file was deleted.

Loading