package de.zalando.spring.cloud.config.aws.kms.it;

import com.amazonaws.services.kms.AWSKMS;
import com.amazonaws.services.kms.model.EncryptRequest;
import com.amazonaws.services.kms.model.InvalidKeyUsageException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.test.context.ActiveProfiles;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;

@SpringBootTest
@ActiveProfiles("asymmetric")
@ExtendWith(OutputCaptureExtension.class)
public class AsymmetricEncryptionNotAvailableTest {

    private static final String PLAINTEXT = "Hello";
    private static final String VERSION_HINT = "Non-symmetric encryption 'RSAES_OAEP_SHA_1' has been configured," +
            "but the version of aws-java-sdk you are using is outdated and does not support it. " +
            "Please upgrade to a more recent version.";

    @Autowired
    private AWSKMS mockKms;

    @Autowired
    private TextEncryptor textEncryptor;

    @Test
    void testAsymmetricEncryptionIsNotAvailable(CapturedOutput output) {
        doThrow(InvalidKeyUsageException.class).when(mockKms).encrypt(any(EncryptRequest.class));

        try {
            // Asymmetric algorithm is not available, because an outdated AWS SDK is used. The textEncryptor will
            // print a warning and fall back to symmetric algorithm.
            // Trying to use an asymmetric key with the symmetric algorithm will lead to an exception.
            textEncryptor.encrypt(PLAINTEXT);
            failBecauseExceptionWasNotThrown(InvalidKeyUsageException.class);
        } catch (InvalidKeyUsageException ignored) {
            assertThat(output).contains(VERSION_HINT);
        }
    }
}

@@ -127,30 +127,154 @@
 s.model.
-EncryptRequest
+DecryptRequest;%0Aimport com.amazonaws.services.kms.model.EncryptRequest;%0Aimport com.amazonaws.services.kms.model.InvalidCiphertextException
 ;%0Aimport
@@ -794,16 +794,70 @@
 files;%0A%0A
+import java.nio.ByteBuffer;%0Aimport java.util.Base64;%0A%0A
 import s
@@ -1064,23 +1064,112 @@
 ito.
-Mockito.doThrow
+ArgumentMatchers.eq;%0Aimport static org.mockito.Mockito.doThrow;%0Aimport static org.mockito.Mockito.verify
 ;%0A%0A@
@@ -1361,16 +1361,73 @@
 Hello%22;%0A
+    private static final String CIPHERTEXT = %22b29wcw==%22;%0A
     priv
@@ -2447,24 +2447,24 @@
  ignored) %7B%0A
-
             
@@ -2502,24 +2502,1258 @@
 SION_HINT);%0A
+            final EncryptRequest expectedRequest = new EncryptRequest()%0A                    .withKeyId(%22an-asymmetric-key%22)%0A                    .withPlaintext(ByteBuffer.wrap(PLAINTEXT.getBytes()));%0A            verify(mockKms).encrypt(eq(expectedRequest));%0A        %7D%0A    %7D%0A%0A    @Test%0A    void testAsymmetricDecryptionIsNotAvailable(CapturedOutput output) %7B%0A        doThrow(InvalidCiphertextException.class).when(mockKms).decrypt(any(DecryptRequest.class));%0A%0A        try %7B%0A            // Asymmetric algorithm is not available, because an outdated AWS SDK is used. The textEncryptor will%0A            // print a warning and fall back to symmetric algorithm.%0A            // Trying to use an asymmetric key with the symmetric algorithm will lead to an exception.%0A            textEncryptor.decrypt(CIPHERTEXT);%0A            failBecauseExceptionWasNotThrown(InvalidCiphertextException.class);%0A        %7D catch (InvalidCiphertextException ignored) %7B%0A            assertThat(output).contains(VERSION_HINT);%0A            final DecryptRequest expectedRequest = new DecryptRequest()%0A                    .withCiphertextBlob(ByteBuffer.wrap(Base64.getDecoder().decode(CIPHERTEXT.getBytes())));%0A            verify(mockKms).decrypt(eq(expectedRequest));%0A
         %7D%0A  

test decryption when asymmetric algorithm is unavailable