CryptoUtil + AwsKms client for encryption/decryption
diff --git a/common/build.gradle b/common/build.gradle index 38f2393..7a13c39 100644 --- a/common/build.gradle +++ b/common/build.gradle
@@ -55,7 +55,10 @@ compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.4' compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: '2.9.8' compile group: 'commons-validator', name: 'commons-validator', version: '1.6' - compile group: 'software.amazon.awssdk', name: 's3', version: '2.5.23' + + compile group: 'software.amazon.awssdk', name: 's3', version: '2.6.5' + compile group: 'software.amazon.awssdk', name: 'kms', version: '2.6.5' + compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" compile "org.jetbrains.kotlin:kotlin-reflect"
diff --git a/common/src/main/kotlin/org/apache/amaterasu/common/crypto/AwsKmsCryptoProvider.kt b/common/src/main/kotlin/org/apache/amaterasu/common/crypto/AwsKmsCryptoProvider.kt new file mode 100644 index 0000000..ef042e0 --- /dev/null +++ b/common/src/main/kotlin/org/apache/amaterasu/common/crypto/AwsKmsCryptoProvider.kt
@@ -0,0 +1,53 @@ +package org.apache.amaterasu.common.crypto + +import com.amazonaws.services.identitymanagement.model.AccessKey +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider +import software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider +import software.amazon.awssdk.core.SdkBytes +import software.amazon.awssdk.services.kms.KmsClient +import software.amazon.awssdk.services.kms.model.DecryptRequest +import software.amazon.awssdk.services.kms.model.EncryptRequest +import software.amazon.awssdk.regions.Region + +class AwsKmsCryptoProvider(override val accessKeyId: String, + override val secretAccessKey: String, + override val region: String) : CryptoKeyProvider { + + private var credentials: AwsCredentialsProvider = if (accessKeyId.isNotEmpty()) { + StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKeyId, secretAccessKey)) + } else { + InstanceProfileCredentialsProvider.builder().build() + } + + val kmsClient = KmsClient.builder().apply { + credentialsProvider(credentials) + region(Region.of(region)) + }.build() + + override fun decryptKey(cipherText: ByteArray): String { + + val decryptRequest = DecryptRequest.builder().apply { + ciphertextBlob(SdkBytes.fromByteArray(cipherText)) + }.build() + + val decryptedValue = kmsClient.decrypt(decryptRequest).plaintext() + + return decryptedValue.asUtf8String() + + } + + override fun encryptKey(keyId: String, value: String): ByteArray? { + + val encryptRequest = EncryptRequest.builder().apply { + keyId(keyId) + plaintext(SdkBytes.fromUtf8String(value)) + }.build() + + val encryptResponse = kmsClient.encrypt(encryptRequest) + + return encryptResponse.ciphertextBlob().asByteArray() + } + +} \ No newline at end of file
diff --git a/common/src/main/kotlin/org/apache/amaterasu/common/crypto/CryptoKeyProvider.kt b/common/src/main/kotlin/org/apache/amaterasu/common/crypto/CryptoKeyProvider.kt new file mode 100644 index 0000000..dfa80bb --- /dev/null +++ b/common/src/main/kotlin/org/apache/amaterasu/common/crypto/CryptoKeyProvider.kt
@@ -0,0 +1,13 @@ +package org.apache.amaterasu.common.crypto + +interface CryptoKeyProvider { + + val accessKeyId: String + val secretAccessKey: String + val region: String + + fun decryptKey(cipherText: ByteArray): String + + fun encryptKey(keyId: String, value: String): ByteArray? + +} \ No newline at end of file
diff --git a/common/src/main/kotlin/org/apache/amaterasu/common/utils/CryptoUtils.kt b/common/src/main/kotlin/org/apache/amaterasu/common/utils/CryptoUtils.kt new file mode 100644 index 0000000..599996f --- /dev/null +++ b/common/src/main/kotlin/org/apache/amaterasu/common/utils/CryptoUtils.kt
@@ -0,0 +1,15 @@ +package org.apache.amaterasu.common.utils + +import org.apache.amaterasu.common.crypto.CryptoKeyProvider + +class CryptoUtils(private val keyProvider: CryptoKeyProvider) { + + fun decryptKey(encryptedKey: ByteArray): String { + return keyProvider.decryptKey(encryptedKey) + } + + fun encryptKey(keyId: String, value: String): ByteArray? { + return keyProvider.encryptKey(keyId, value) + } + +} \ No newline at end of file
diff --git a/common/src/test/kotlin/org/apache/amaterasu/common/utils/CryptoUtilsTest.kt b/common/src/test/kotlin/org/apache/amaterasu/common/utils/CryptoUtilsTest.kt new file mode 100644 index 0000000..2cd23cb --- /dev/null +++ b/common/src/test/kotlin/org/apache/amaterasu/common/utils/CryptoUtilsTest.kt
@@ -0,0 +1,33 @@ +package org.apache.amaterasu.common.utils + +import org.apache.amaterasu.common.crypto.AwsKmsCryptoProvider +import org.jetbrains.spek.api.Spek +import org.jetbrains.spek.api.dsl.given +import org.jetbrains.spek.api.dsl.it +import org.jetbrains.spek.api.dsl.on +import org.junit.Assert.* + + +//class CryptoUtilsTest : Spek({ +// +// given("an aws key and value") { +// val keyId = "arn:aws:kms:" +// val clearText = "Value to encrypt" +// +// on ("encrypting and decrypting") { +// +// val kmsClient = CryptoUtils(AwsKmsCryptoProvider( +// accessKeyId = "", +// secretAccessKey = "", +// region = "ap-southeast-2")) +// val encryptedText = kmsClient.encryptKey(keyId, clearText)!! +// +// val decryptedText = kmsClient.decryptKey(encryptedText) +// +// it("decrypted value is the same as the clear text") { +// assertEquals(clearText, decryptedText) +// } +// } +// } +// +//}) \ No newline at end of file