Skip to content
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
7fde3c0
build: open feign 의존성 추가
juanxiu Oct 14, 2025
ac7d8f2
feat: 애플리케이션에서 openfeign 어노테이션 등록
juanxiu Oct 14, 2025
4822282
feat: SampleClient 구현
juanxiu Oct 14, 2025
f9bb453
feat: vpc, subnet, sg requestDto
juanxiu Oct 14, 2025
0999889
feat: CloudProviderService interface 구현
juanxiu Oct 14, 2025
77ca004
feat: SampleCloudProviderService 구현체
juanxiu Oct 14, 2025
46fade2
feat: 테넌트 격리 이벤트와 리스너 구현
juanxiu Oct 14, 2025
41b7420
feat: TenantIsolationService 테넌트 격리 정책 서비스
juanxiu Oct 14, 2025
c551784
feat: CloudResourceResult Dto 구현
juanxiu Oct 14, 2025
8a71bcf
Merge branch 'develop' of github.com:CCCloudPlatform/AgenticCP-Core i…
juanxiu Oct 14, 2025
793869e
Merge
juanxiu Oct 15, 2025
9dfbe0b
feat: SampleCloudProviderService 보안그룹 메서드
juanxiu Oct 15, 2025
a7459f5
feat: 격리 결과와 상태용 DTO
juanxiu Oct 15, 2025
35db24e
feat: 테넌트 격리 정책 인터페이스
juanxiu Oct 15, 2025
e08f2c8
feat: 테넌트 격리 정책 인터페이스 생성하는 팩토리
juanxiu Oct 15, 2025
0188b52
feat: TenantIsolationService에 격리 정책 적용 메서드까지 구현
juanxiu Oct 15, 2025
4143d47
feat: 불필요한 파일 삭제
juanxiu Oct 24, 2025
3fa5631
refactor: 파일 구조 변경
juanxiu Oct 24, 2025
3d41db7
feat: 리소스 생성 인터페이스, 요청, 샘플 구현체
juanxiu Oct 24, 2025
613e924
feat: Isolationstrategy 인터페이스와 팩토리
juanxiu Oct 24, 2025
8e0e05f
feat: SharedIsolationStrategy 구현체
juanxiu Oct 24, 2025
b7d9c29
feat: AwstenantIsolationAdapter 컴포넌트
juanxiu Oct 24, 2025
38c9af4
feat: AwsCloudResourceCreator 샘플 리소스 생성 구현체
juanxiu Oct 24, 2025
2694e7e
feat: IsolationStrategyFactory 맵 조회 로직 수정
juanxiu Oct 24, 2025
a571027
Merge branch 'develop' of github.com:CCCloudPlatform/AgenticCP-Core i…
juanxiu Oct 24, 2025
d5e6826
refactor: 파일 구조 변경
juanxiu Oct 24, 2025
28ed9d6
Merge branch 'develop' of github.com:CCCloudPlatform/AgenticCP-Core i…
juanxiu Oct 24, 2025
f37f976
Merge branch 'develop' of github.com:CCCloudPlatform/AgenticCP-Core i…
juanxiu Nov 8, 2025
f6c971f
Merge branch 'develop' of github.com:CCCloudPlatform/AgenticCP-Core i…
juanxiu Nov 23, 2025
e7e5366
refactor: Organization-Tenant 관계를 1:N에서 1:1로 변경
juanxiu Nov 24, 2025
42952f3
feat: TenantIsolationService 재작성 및 Repository 추가
juanxiu Nov 24, 2025
16a1614
feat: 리소스 소유권 관리 엔티티 및 서비스 추가
juanxiu Nov 24, 2025
f472da1
feat: 리소스 접근 제어 서비스 및 CloudResourceService 통합
juanxiu Nov 24, 2025
3c6a1e7
test: 테넌트 격리 수준 정책 관련 서비스 테스트 추가
juanxiu Nov 24, 2025
104e621
fix: AwsTenantIsolationAdapter 및 AwsCloudResourceCreator 수정
juanxiu Nov 24, 2025
7be9b4d
docs: 테넌트 격리 수준 정책 구현 문서 추가
juanxiu Nov 24, 2025
04d755e
fix: FeatureFlagAuditServiceTest requestPath 누락 오류 해결 - AuditEventBui…
juanxiu Nov 24, 2025
8f647fd
Revert "fix: FeatureFlagAuditServiceTest requestPath 누락 오류 해결 - Audit…
juanxiu Nov 24, 2025
739d4ed
Merge branch 'develop' of github.com:CCCloudPlatform/AgenticCP-Core i…
juanxiu Nov 24, 2025
1dec198
Merge branch 'develop' of github.com:CCCloudPlatform/AgenticCP-Core i…
juanxiu Dec 7, 2025
fd9e787
Merge: 충돌 해결 완료
juanxiu Dec 16, 2025
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
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,13 @@
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>4.1.3</version>
</dependency>

<!-- Awaitility for async testing -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableJpaRepositories
@EnableAsync
@EnableScheduling
public class AgenticCpCoreApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.agenticcp.core.domain.tenant.adapter;

import com.agenticcp.core.domain.tenant.entity.TenantIsolation;
import com.agenticcp.core.domain.tenant.adapter.dto.IsolationResult;
import com.agenticcp.core.domain.tenant.adapter.dto.IsolationStatus;

/**
* 테넌트 격리 정책을 적용하는 핵심 인터페이스
* Adapter 패턴의 Target Interface 역할
*/
public interface TenantIsolationAdapter {

/**
* 테넌트에 격리 정책을 적용합니다.
*
* @param tenantKey 테넌트 키
* @param isolation 격리 정책 정보
* @return 격리 정책 적용 결과
*/
IsolationResult applyIsolationPolicy(String tenantKey, TenantIsolation isolation);

/**
* 테넌트의 격리 정책을 제거합니다.
*
* @param tenantKey 테넌트 키
*/
void removeIsolationPolicy(String tenantKey);

/**
* 테넌트의 현재 격리 상태를 조회합니다.
*
* @param tenantKey 테넌트 키
* @return 격리 상태 정보
*/
IsolationStatus getIsolationStatus(String tenantKey);

/**
* 특정 격리 레벨을 지원하는지 확인합니다.
*
* @param isolationLevel 격리 레벨
* @return 지원 여부
*/
boolean supportsIsolationLevel(TenantIsolation.IsolationLevel isolationLevel);

/**
* 이 Adapter가 지원하는 클라우드 프로바이더 타입을 반환합니다.
*
* @return 클라우드 프로바이더 타입
*/
String getSupportedCloudProvider();

Choose a reason for hiding this comment

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

여기서 반환하는 프로바이더 반환 타입을 CloudProviderType으로 하면 타입 안정성이 더 높아지지 않을까융
String으로 반환하는 이유가 따로 있으려나용? 코드를 다 보진 않아가지구

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

오아 좋은 생각이네요!! 감사합니닷 ~

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

코드리뷰 넘나 환영 .. 더 주세요 히

Choose a reason for hiding this comment

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

기능 푸시하고 요청주면 리뷰할게용~~!

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.agenticcp.core.domain.tenant.adapter;

import com.agenticcp.core.domain.tenant.controller.cloud.CloudProviderType;
import com.agenticcp.core.domain.tenant.entity.TenantIsolation;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* TenantIsolationAdapter 인스턴스를 생성하는 Factory
* Adapter 패턴의 Factory 역할
*/
@Component
public class TenantIsolationAdapterFactory {

private final Map<CloudProviderType, TenantIsolationAdapter> adapters;

public TenantIsolationAdapterFactory(List<TenantIsolationAdapter> adapterList) {
this.adapters = adapterList.stream()
.collect(Collectors.toMap(
adapter -> CloudProviderType.valueOf(adapter.getSupportedCloudProvider()),
Function.identity()
));
}

/**
* 클라우드 프로바이더 타입에 해당하는 Adapter를 반환합니다.
*
* @param providerType 클라우드 프로바이더 타입
* @return 해당하는 Adapter 인스턴스
* @throws IllegalArgumentException 지원하지 않는 프로바이더 타입인 경우
*/
public TenantIsolationAdapter getAdapter(CloudProviderType providerType) {
TenantIsolationAdapter adapter = adapters.get(providerType);
if (adapter == null) {
throw new IllegalArgumentException("Unsupported cloud provider type: " + providerType);
}
return adapter;
}

/**
* 특정 격리 레벨을 지원하는 Adapter 목록을 반환합니다.
*
* @param isolationLevel 격리 레벨
* @return 해당 격리 레벨을 지원하는 Adapter 목록
*/
public List<TenantIsolationAdapter> getAdaptersSupporting(TenantIsolation.IsolationLevel isolationLevel) {
return adapters.values().stream()
.filter(adapter -> adapter.supportsIsolationLevel(isolationLevel))
.toList();
}

/**
* 사용 가능한 모든 Adapter 목록을 반환합니다.
*
* @return 모든 Adapter 목록
*/
public List<TenantIsolationAdapter> getAllAdapters() {
return List.copyOf(adapters.values());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.agenticcp.core.domain.tenant.adapter.dto;

import com.agenticcp.core.domain.tenant.entity.TenantIsolation;
import lombok.Builder;

import java.time.LocalDateTime;
import java.util.Map;

/**
* 격리 정책 적용 결과를 담는 DTO
*/
@Builder
public record IsolationResult(
boolean success,
String message,
String tenantKey,
TenantIsolation.IsolationLevel isolationLevel,
LocalDateTime appliedAt,
Map<String, Object> resourceDetails, // CSP별 생성된 리소스 정보
Map<String, String> errors // 오류 정보
) {

public static IsolationResult success(String tenantKey, TenantIsolation.IsolationLevel level,
Map<String, Object> resourceDetails) {
return IsolationResult.builder()
.success(true)
.message("Isolation policy applied successfully")
.tenantKey(tenantKey)
.isolationLevel(level)
.appliedAt(LocalDateTime.now())
.resourceDetails(resourceDetails)
.build();
}

public static IsolationResult failure(String tenantKey, String message, Map<String, String> errors) {
return IsolationResult.builder()
.success(false)
.message(message)
.tenantKey(tenantKey)
.appliedAt(LocalDateTime.now())
.errors(errors)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.agenticcp.core.domain.tenant.adapter.dto;

import com.agenticcp.core.domain.tenant.entity.TenantIsolation;
import lombok.Builder;

import java.time.LocalDateTime;
import java.util.Map;

/**
* 테넌트의 격리 상태 정보를 담는 DTO
*/
@Builder
public record IsolationStatus(
String tenantKey,
TenantIsolation.IsolationLevel isolationLevel,
boolean isActive,
LocalDateTime lastUpdated,
Map<String, Object> resourceStatus, // CSP별 리소스 상태
Map<String, String> configuration // 현재 설정 정보
) {

public static IsolationStatus inactive(String tenantKey) {
return IsolationStatus.builder()
.tenantKey(tenantKey)
.isActive(false)
.lastUpdated(LocalDateTime.now())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.agenticcp.core.domain.tenant.controller.cloud;

import lombok.Getter;

@Getter
public enum CloudProviderType {
AWS,
AZURE,
GCP,
OTHER
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.agenticcp.core.domain.tenant.controller.cloud;

import com.agenticcp.core.domain.tenant.controller.cloud.dto.CloudResourceResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

@FeignClient(
name = "",
url = ""
)
public interface SampleClient {

@PostMapping("/api/{samplePathVariable}")
CloudResourceResult createVpc(
@PathVariable String samplePathVariable,
@RequestBody String sampleRequestBody
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.agenticcp.core.domain.tenant.controller.cloud.dto;

import lombok.Builder;

import java.util.Map;

@Builder
public record CloudResourceResult(
String resourceId,
Map<String, Object> metadata
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.agenticcp.core.domain.tenant.controller.cloud.dto;

import lombok.Builder;

import java.util.List;

@Builder
public record SecurityGroupRequest(
String vpcId,
String name,
List<SecurityGroupRule> securityGroupRules
) {
public record SecurityGroupRule(
String protocol,
String portRange,
String cidrIp
) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.agenticcp.core.domain.tenant.controller.cloud.dto;

import lombok.Builder;

import java.util.List;

@Builder
public record SubnetRequest(
String vpcId,
List<SubnetConfig> subnets
) {
public record SubnetConfig(
String subnetId,
String availabilityZone
) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.agenticcp.core.domain.tenant.controller.cloud.dto;

import java.util.Map;

public record VpcRequest(
String cidrBlock,
String region,
Map<String, String> tags
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.agenticcp.core.domain.tenant.controller.cloud.service;


import com.agenticcp.core.domain.tenant.controller.cloud.CloudProviderType;
import com.agenticcp.core.domain.tenant.controller.cloud.dto.CloudResourceResult;
import com.agenticcp.core.domain.tenant.controller.cloud.dto.SecurityGroupRequest;
import com.agenticcp.core.domain.tenant.controller.cloud.dto.SubnetRequest;
import com.agenticcp.core.domain.tenant.controller.cloud.dto.VpcRequest;

public interface CloudProviderService {

CloudProviderType getCloudProviderType();

CloudResourceResult createVpc(String tenantKey, VpcRequest vpcRequest);

CloudResourceResult createSubnets(String tenantKey, SubnetRequest subnetRequest);

CloudResourceResult createSecurityGroups(String tenantKey, SecurityGroupRequest securityGroupRequest);





}
Loading
Loading