AWS Marketplace 연동 가이드 | 01. AWS Marketplace Seller 계정 생성부터 x-amzn-marketplace-token 토큰 수신까지
AWS Marketplace 연동 가이드 | 02. AWS Marketplace Client 생성하기
AWS Marketplace 연동 가이드 | 03. ResolveCustomer
AWS Marketplace 연동 가이드 | 04. BatchMeterUsage
AWS Marketplace Client 생성하기
AWS Marketplace Client를 생성하는 방법은 아래와 같습니다.
public AWSMarketplaceMetering createAWSMarketplaceClient(){
AWSMarketplaceMeteringClientBuilder builder = AWSMarketplaceMeteringClientBuilder.standard();
return builder.build();
}
그런데 Client를 생성하는 과정에서 Credential 정보가 필요합니다. AWSMarketplaceMeteringClientBuilder 클래스의 설명을 읽어보면 DefaultAWSCredentialsProviderChain, DefaultAwsRegionProviderChain를 사용하는 것을 알 수 있습니다.

이 클래스들의 설명을 읽어보면 가장 기본적으로 SystemProperties 정보에 지정된 값을 사용하는 것을 알 수 있습니다. 각각의 클래스에서 지정하라고 하는 값은 아래와 같이 설정할 수 있습니다.
private void setAwsRegionProps() {
System.setProperty("aws.region", conf.aws_marketplace_region);
}
private void setAwsMarketplaceClientProps() {
// @See com.amazonaws.services.marketplacemetering.AWSMarketplaceMeteringClientBuilder#defaultClient
// @See com.amazonaws.auth.DefaultAWSCredentialsProviderChain
System.setProperty("aws.accessKeyId", conf.aws_marketplace_access_key);
System.setProperty("aws.secretKey", conf.aws_marketplace_secret_access_key);
}
각 프로퍼티의 값을 어떻게 찾는지 모른다면 아래의 링크를 확인해주세요.
2024.01.16 - [개발/AWS Marketplace] - AWS Marketplace API Region 확인하는 방법
2024.01.16 - [개발/AWS Marketplace] - AWS API에 사용할 Access Key, Access Secret Key 발급하는 방법
2024.01.16 - [개발/AWS Marketplace] - AWS API에서 AccessKey, SecretAccessKey 대신 Role ARN 사용하기
여기까지 설정해주면 아래와 같이 client를 생성할 수 있습니다.
@Service
public class AwsMarketplaceApiService {
private AWSMarketplaceMetering client;
@PostConstruct
public void init(){
AWSMarketplaceMeteringClientBuilder builder = AWSMarketplaceMeteringClientBuilder.standard();
client = builder.build();
}
}
💡Access Key, Access Secret Key 대신 Role ARN를 사용해야한다면
아래의 문서를 확인해주세요.
2024.01.16 - [개발/AWS Marketplace] - AWS API에서 AccessKey, SecretAccessKey 대신 Role ARN 사용하기
System.setProperty를 하지 않을뿐, AWSMarketplaceMetering client를 생성하는 로직은 그대로 사용할 수 있습니다.
💡AWS Marketplace Seller 계정과 EC2 관리 계정이 다르다면
아래의 문서를 확인해주세요.
2024.01.17 - [개발/AWS Marketplace] - AWS Marketplace AssumeRole 적용하기
본 문서에서 다루는 모든 개념이 적용된 코드는 아래 Gist에서 확인할 수 있습니다.
import com.amazonaws.auth.AWSStaticCredentialsProvider; | |
import com.amazonaws.auth.BasicSessionCredentials; | |
import com.amazonaws.services.marketplacemetering.AWSMarketplaceMetering; | |
import com.amazonaws.services.marketplacemetering.AWSMarketplaceMeteringClientBuilder; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import org.springframework.stereotype.Service; | |
import software.amazon.awssdk.services.sts.StsClient; | |
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest; | |
import software.amazon.awssdk.services.sts.model.AssumeRoleResponse; | |
import software.amazon.awssdk.services.sts.model.Credentials; | |
import javax.annotation.PostConstruct; | |
import java.time.Instant; | |
@Service | |
public class CreateAwsMarketplaceClient { | |
private final Long NOT_INITIALIZED = 0L; | |
private final Logger logger = LoggerFactory.getLogger(CreateAwsMarketplaceClient.class); | |
private final Configure conf = Configure.getInstance(); | |
private StsClient stsClient; | |
private AWSMarketplaceMetering marketplaceClient; | |
private long assumeRoleExpirationTime = NOT_INITIALIZED; | |
@PostConstruct | |
public void initClient() { | |
try { | |
if (conf.enable_aws_marketplace == false) { | |
return; | |
} | |
// 운영 환경에서는 system props를 사용하지 않음 | |
// @See software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider | |
if (conf.enable_aws_marketplace_system_properties) { | |
setAwsRegionProps(); | |
setAwsClientProps(); | |
} | |
getAwsMarketplaceClient(); | |
} catch (Exception e) { | |
logger.error("[AWS MP] " + e.getMessage(), e); | |
} | |
} | |
private void setAwsClientProps() { | |
/** | |
* | |
* The 'ResolveCustomer' API needs to called from the seller account id | |
* used to publish the SaaS application to successfully resolve the token. | |
* @See https://docs.aws.amazon.com/marketplacemetering/latest/APIReference/API_ResolveCustomer.html | |
* | |
* 아래의 설정에 seller가 아닌 다른 계정의 API KEY를 지정하는 경우, assume_role을 사용해야한다 | |
* conf.aws_marketplace_access_key, conf.aws_marketplace_secret_access_key | |
*/ | |
if (conf.enable_aws_marketplace_assume_role) { | |
setStsClientProps(); | |
} else { | |
setAwsMarketplaceClientProps(); | |
} | |
} | |
private void setAwsRegionProps() { | |
System.setProperty("aws.region", conf.aws_marketplace_region); | |
} | |
private void setStsClientProps() { | |
// @See software.amazon.awssdk.services.sts.StsClient.create | |
// @See software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider | |
System.setProperty("aws.accessKeyId", conf.aws_marketplace_access_key); | |
System.setProperty("aws.secretAccessKey", conf.aws_marketplace_secret_access_key); | |
} | |
private void setAwsMarketplaceClientProps() { | |
// @See com.amazonaws.services.marketplacemetering.AWSMarketplaceMeteringClientBuilder#defaultClient | |
// @See com.amazonaws.auth.DefaultAWSCredentialsProviderChain | |
System.setProperty("aws.accessKeyId", conf.aws_marketplace_access_key); | |
System.setProperty("aws.secretKey", conf.aws_marketplace_secret_access_key); | |
} | |
private AWSMarketplaceMetering getAwsMarketplaceClient() throws CustomError { | |
try { | |
updateAwsMarketplaceClient(); | |
return this.marketplaceClient; | |
} catch (Exception e) { | |
logger.error("[AWS MP] " + e.getMessage(), e); | |
} | |
throw new CustomError(ModuleName.ACCOUNT, ErrorType.INTERNAL_SERVER_ERROR); | |
} | |
private void updateAwsMarketplaceClient(){ | |
if (conf.enable_aws_marketplace_assume_role) { | |
if (this.assumeRoleExpirationTime == NOT_INITIALIZED || this.assumeRoleExpirationTime < DateUtil.now()) { | |
StsClient stsClient = getStsClient(); | |
Credentials credentials = assumeRole(stsClient, conf.aws_marketplace_assume_role_arn); | |
AWSMarketplaceMeteringClientBuilder builder = AWSMarketplaceMeteringClientBuilder.standard(); | |
BasicSessionCredentials basicSessionCredentials = new BasicSessionCredentials( | |
credentials.accessKeyId(), | |
credentials.secretAccessKey(), | |
credentials.sessionToken()); | |
builder.setCredentials(new AWSStaticCredentialsProvider(basicSessionCredentials)); | |
this.marketplaceClient = builder.build(); | |
logger.info("[AWS MP] client initialized success"); | |
} | |
} else { | |
if (this.marketplaceClient == null) { | |
AWSMarketplaceMeteringClientBuilder builder = AWSMarketplaceMeteringClientBuilder.standard(); | |
this.marketplaceClient = builder.build(); | |
logger.info("[AWS MP] client initialized success"); | |
} | |
} | |
} | |
private StsClient getStsClient() { | |
if (stsClient != null) { | |
return stsClient; | |
} | |
stsClient = StsClient.create(); | |
return stsClient; | |
} | |
/** | |
* @param stsClient | |
* @param roleArn 3가지 조건을 만족해야 함 | |
* 1. AWS Marketplace Seller 계정에서 생성한 Role | |
* 2. 다음 2가지 권한을 가진 Role | |
* - "aws-marketplace:BatchMeterUsage" | |
* - "aws-marketplace:ResolveCustomer" | |
* 3. 운영 환경에서 Instance를 관리할 계정이 Trusted entities로 설정되어야 함 | |
*/ | |
private Credentials assumeRole(StsClient stsClient, String roleArn) { | |
AssumeRoleRequest roleRequest = AssumeRoleRequest.builder() | |
.roleArn(roleArn) | |
.roleSessionName("aws-mp-session-" + DateUtil.now()) | |
.build(); | |
AssumeRoleResponse roleResponse = stsClient.assumeRole(roleRequest); | |
Credentials myCreds = roleResponse.credentials(); | |
Instant exTime = myCreds.expiration(); | |
assumeRoleExpirationTime = exTime.toEpochMilli(); | |
logger.info("[AWS AssumeRole] success. assumeRoleExpiredTime : {}", DateUtil.datetime(assumeRoleExpirationTime)); | |
return myCreds; | |
} | |
} |
'AWS > AWS Marketplace' 카테고리의 다른 글
AWS Marketplace 연동 가이드 | 04. BatchMeterUsage (0) | 2024.01.17 |
---|---|
AWS Marketplace 연동 가이드 | 03. ResolveCustomer (0) | 2024.01.17 |
AWS Marketplace 연동 가이드 | 01. AWS Marketplace Seller 계정 생성부터 x-amzn-marketplace-token 토큰 수신까지 (0) | 2024.01.17 |
AWS Marketplace AssumeRole 적용하기 (0) | 2024.01.17 |
AWS API에서 AccessKey, SecretAccessKey 대신 Role ARN 사용하기 (0) | 2024.01.16 |