AWS/AWS Marketplace

AWS Marketplace 연동 가이드 | 02. AWS Marketplace Client 생성하기

행운개발자 2024. 1. 17. 01:17
728x90

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;
}
}

728x90