Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate server common library to use aws sdk v2 #2677

Merged
merged 1 commit into from
Aug 9, 2024
Merged
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
17 changes: 11 additions & 6 deletions libs/java/server_common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,19 @@
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>${aws.version}</version>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>${aws2.version}</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>kms</artifactId>
<version>${aws2.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-ses</artifactId>
<version>${aws.version}</version>
<groupId>software.amazon.awssdk</groupId>
<artifactId>sesv2</artifactId>
<version>${aws2.version}</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@

package com.yahoo.athenz.auth.impl.aws;

import com.amazonaws.services.kms.AWSKMS;
import com.amazonaws.services.kms.AWSKMSClientBuilder;
import com.amazonaws.services.kms.model.DecryptRequest;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectInputStream;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.kms.KmsClient;
import software.amazon.awssdk.services.kms.model.DecryptRequest;
import software.amazon.awssdk.services.kms.model.DecryptResponse;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import com.yahoo.athenz.auth.PrivateKeyStore;
import com.yahoo.athenz.auth.ServerPrivateKey;
import com.yahoo.athenz.auth.util.Crypto;
import org.eclipse.jetty.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;

/**
Expand All @@ -46,10 +46,6 @@
* responsible for decrypting data.
* AmazonS3 lib defaults to reading from S3 buckets created under us-east-1 unless
* its explicitly specified using system property or aws config
*
* @author charlesk
* See http://docs.aws.amazon.com/kms/latest/developerguide/programming-encryption.html
* See http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/examples-s3-objects.html
*/
public class AwsPrivateKeyStore implements PrivateKeyStore {

Expand All @@ -71,26 +67,28 @@ public class AwsPrivateKeyStore implements PrivateKeyStore {
private static final String ZMS_SERVICE = "zms";
private static final String ZTS_SERVICE = "zts";

private final AmazonS3 s3;
private final AWSKMS kms;
private final S3Client s3;
private final KmsClient kms;
private boolean kmsDecrypt;

public AwsPrivateKeyStore() {
this(initAmazonS3(), initAWSKMS());
kmsDecrypt = Boolean.parseBoolean(System.getProperty(ATHENZ_PROP_AWS_KMS_DECRYPT, "false"));
}

private static AWSKMS initAWSKMS() {
private static KmsClient initAWSKMS() {
final String kmsRegion = System.getProperty(ATHENZ_PROP_AWS_KMS_REGION);
return StringUtil.isEmpty(kmsRegion) ? AWSKMSClientBuilder.defaultClient() : AWSKMSClientBuilder.standard().withRegion(kmsRegion).build();
return StringUtil.isEmpty(kmsRegion) ? KmsClient.create() :
KmsClient.builder().region(Region.of(kmsRegion)).build();
}

private static AmazonS3 initAmazonS3() {
private static S3Client initAmazonS3() {
final String s3Region = System.getProperty(ATHENZ_PROP_AWS_S3_REGION);
return StringUtil.isEmpty(s3Region) ? AmazonS3ClientBuilder.defaultClient() : AmazonS3ClientBuilder.standard().withRegion(s3Region).build();
return StringUtil.isEmpty(s3Region) ? S3Client.create() :
S3Client.builder().region(Region.of(s3Region)).build();
}

public AwsPrivateKeyStore(final AmazonS3 s3, final AWSKMS kms) {
public AwsPrivateKeyStore(final S3Client s3, final KmsClient kms) {
this.s3 = s3;
this.kms = kms;
}
Expand Down Expand Up @@ -141,47 +139,40 @@ public char[] getSecret(final String appName, final String keygroupName, final S
private String getDecryptedData(final String bucketName, final String keyName) {

String keyValue = "";
S3Object s3Object = getS3().getObject(bucketName, keyName);


if (LOG.isDebugEnabled()) {
LOG.debug("retrieving appName {}, key {}", bucketName, keyName);
}

if (null == s3Object) {
LOG.error("error retrieving key {}, from bucket {}", keyName, bucketName);
return keyValue;
}

try (S3ObjectInputStream s3InputStream = s3Object.getObjectContent();
ByteArrayOutputStream result = new ByteArrayOutputStream()) {

byte[] buffer = new byte[1024];
int length;
while ((length = s3InputStream.read(buffer)) != -1) {
result.write(buffer, 0, length);
}

GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(bucketName).key(keyName).build();

try (ResponseInputStream<GetObjectResponse> responseInputStream = getS3().getObject(getObjectRequest)) {

byte[] result = responseInputStream.readAllBytes();

// if key should be decrypted, do so with KMS

if (kmsDecrypt) {
DecryptRequest req = new DecryptRequest().withCiphertextBlob(ByteBuffer.wrap(result.toByteArray()));
ByteBuffer plainText = getKMS().decrypt(req).getPlaintext();
keyValue = new String(plainText.array());
DecryptRequest decryptRequest = DecryptRequest.builder()
.ciphertextBlob(SdkBytes.fromByteArray(result)).build();
DecryptResponse decryptResponse = getKMS().decrypt(decryptRequest);
keyValue = decryptResponse.plaintext().asString(StandardCharsets.UTF_8);
} else {
keyValue = result.toString();
keyValue = new String(result);
}

} catch (IOException e) {
LOG.error("error getting application secret.", e);
} catch (Exception ex) {
LOG.error("error getting application secret.", ex);
}

return keyValue.trim();
}

AmazonS3 getS3() {
S3Client getS3() {
return s3;
}

AWSKMS getKMS() {
KmsClient getKMS() {
return kms;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@

package com.yahoo.athenz.common.server.notification.impl;

import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder;
import com.amazonaws.services.simpleemail.model.RawMessage;
import com.amazonaws.services.simpleemail.model.SendRawEmailRequest;
import com.amazonaws.services.simpleemail.model.SendRawEmailResult;
import com.yahoo.athenz.common.server.util.Utils;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sesv2.SesV2Client;
import software.amazon.awssdk.services.sesv2.model.*;
import com.yahoo.athenz.common.server.notification.EmailProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -34,18 +32,31 @@

public class AWSEmailProvider implements EmailProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(AWSEmailProvider.class);
private final AmazonSimpleEmailService ses;
private final SesV2Client ses;

@Override
public boolean sendEmail(Collection<String> recipients, String from, MimeMessage mimeMessage) {

try {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
mimeMessage.writeTo(outputStream);
RawMessage rawMessage = new RawMessage(ByteBuffer.wrap(outputStream.toByteArray()));
SendRawEmailRequest rawEmailRequest = new SendRawEmailRequest(rawMessage);
SendRawEmailResult result = ses.sendRawEmail(rawEmailRequest);

SendEmailRequest emailRequest = SendEmailRequest.builder()
.fromEmailAddress(from)
.destination(Destination.builder()
.toAddresses(recipients)
.build())
.content(EmailContent.builder()
.raw(RawMessage.builder()
.data(SdkBytes.fromByteBuffer(ByteBuffer.wrap(outputStream.toByteArray())))
.build())
.build())
.build();

SendEmailResponse result = ses.sendEmail(emailRequest);

if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Email with messageId={} sent successfully.", result.getMessageId());
LOGGER.debug("Email with messageId={} sent successfully.", result.messageId());
}
return result != null;
}
Expand All @@ -59,15 +70,12 @@ public AWSEmailProvider() {
this(initSES());
}

AWSEmailProvider(AmazonSimpleEmailService ses) {
AWSEmailProvider(SesV2Client ses) {
this.ses = ses;
}

private static AmazonSimpleEmailService initSES() {
Region region = Regions.getCurrentRegion();
if (region == null) {
region = Region.getRegion(Regions.US_EAST_1);
}
return AmazonSimpleEmailServiceClientBuilder.standard().withRegion(region.getName()).build();
private static SesV2Client initSES() {
Region region = Utils.getAwsRegion(Region.US_EAST_1);
return SesV2Client.builder().region(region).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package com.yahoo.athenz.common.server.notification.impl;

import com.amazonaws.util.IOUtils;
import software.amazon.awssdk.utils.IoUtils;
import com.yahoo.athenz.common.server.notification.EmailProvider;
import com.yahoo.athenz.common.server.notification.Notification;
import com.yahoo.athenz.common.server.notification.NotificationEmail;
Expand Down Expand Up @@ -74,7 +74,7 @@ byte[] readBinaryFromFile(String fileName) {
if (resource != null) {
try (InputStream fileStream = resource.openStream()) {
//convert to byte array
fileByteArray = IOUtils.toByteArray(fileStream);
fileByteArray = IoUtils.toByteArray(fileStream);

} catch (IOException ex) {
LOGGER.error("Could not read file: {}. Error message: {}", fileName, ex.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

package com.yahoo.athenz.common.server.paramstore;

import com.amazonaws.util.EC2MetadataUtils;
import com.yahoo.athenz.common.server.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.regions.Region;
Expand Down Expand Up @@ -76,10 +76,8 @@ private String[] loadParamPrefixes() {

SsmClient initClient() {
try {
String region = EC2MetadataUtils.getInstanceInfo().getRegion();
return SsmClient.builder()
.region(Region.of(region))
.build();
Region region = Utils.getAwsRegion(Region.US_EAST_1);
return SsmClient.builder().region(region).build();
} catch (Exception ex) {
LOG.error("Failed to init aws ssm client", ex);
}
Expand Down
Loading
Loading