Wrap Kms decrypt with Retrier

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=154861871
This commit is contained in:
guyben 2017-05-02 12:07:16 -07:00 committed by Ben McIlwain
parent 7f2821cd7e
commit 5e7834b00e
3 changed files with 37 additions and 15 deletions

View file

@ -27,7 +27,9 @@ import com.google.api.services.cloudkms.v1beta1.model.KeyRing;
import com.google.api.services.cloudkms.v1beta1.model.UpdateCryptoKeyPrimaryVersionRequest; import com.google.api.services.cloudkms.v1beta1.model.UpdateCryptoKeyPrimaryVersionRequest;
import google.registry.config.RegistryConfig.Config; import google.registry.config.RegistryConfig.Config;
import google.registry.keyring.api.KeyringException; import google.registry.keyring.api.KeyringException;
import google.registry.util.Retrier;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.Callable;
import javax.inject.Inject; import javax.inject.Inject;
/** The {@link KmsConnection} which talks to Cloud KMS. */ /** The {@link KmsConnection} which talks to Cloud KMS. */
@ -41,14 +43,17 @@ class KmsConnectionImpl implements KmsConnection {
private final CloudKMS kms; private final CloudKMS kms;
private final String kmsKeyRingName; private final String kmsKeyRingName;
private final String projectId; private final String projectId;
private final Retrier retrier;
@Inject @Inject
KmsConnectionImpl( KmsConnectionImpl(
@Config("cloudKmsProjectId") String projectId, @Config("cloudKmsProjectId") String projectId,
@Config("cloudKmsKeyRing") String kmsKeyringName, @Config("cloudKmsKeyRing") String kmsKeyringName,
Retrier retrier,
CloudKMS kms) { CloudKMS kms) {
this.projectId = projectId; this.projectId = projectId;
this.kmsKeyRingName = kmsKeyringName; this.kmsKeyRingName = kmsKeyringName;
this.retrier = retrier;
this.kms = kms; this.kms = kms;
} }
@ -129,8 +134,23 @@ class KmsConnectionImpl implements KmsConnection {
} }
@Override @Override
public byte[] decrypt(String cryptoKeyName, String encodedCiphertext) { public byte[] decrypt(final String cryptoKeyName, final String encodedCiphertext) {
try { try {
return retrier.callWithRetry(
new Callable<byte[]>() {
@Override
public byte[] call() throws IOException {
return attemptDecrypt(cryptoKeyName, encodedCiphertext);
}
},
IOException.class);
} catch (RuntimeException e) {
throw new KeyringException(
String.format("CloudKMS decrypt operation failed for secret %s", cryptoKeyName), e);
}
}
private byte[] attemptDecrypt(String cryptoKeyName, String encodedCiphertext) throws IOException{
return kms.projects() return kms.projects()
.locations() .locations()
.keyRings() .keyRings()
@ -140,10 +160,6 @@ class KmsConnectionImpl implements KmsConnection {
new DecryptRequest().setCiphertext(encodedCiphertext)) new DecryptRequest().setCiphertext(encodedCiphertext))
.execute() .execute()
.decodePlaintext(); .decodePlaintext();
} catch (IOException e) {
throw new KeyringException(
String.format("CloudKMS decrypt operation failed for secret %s", cryptoKeyName), e);
}
} }
private static String getLocationName(String projectId) { private static String getLocationName(String projectId) {

View file

@ -18,6 +18,7 @@ java_library(
"//java/google/registry/keyring/api", "//java/google/registry/keyring/api",
"//java/google/registry/keyring/kms", "//java/google/registry/keyring/kms",
"//java/google/registry/model", "//java/google/registry/model",
"//java/google/registry/util",
"//javatests/google/registry/testing", "//javatests/google/registry/testing",
"//third_party/java/objectify:objectify-v4_1", "//third_party/java/objectify:objectify-v4_1",
"@com_google_api_client", "@com_google_api_client",

View file

@ -34,6 +34,9 @@ import com.google.api.services.cloudkms.v1beta1.model.EncryptRequest;
import com.google.api.services.cloudkms.v1beta1.model.EncryptResponse; import com.google.api.services.cloudkms.v1beta1.model.EncryptResponse;
import com.google.api.services.cloudkms.v1beta1.model.KeyRing; import com.google.api.services.cloudkms.v1beta1.model.KeyRing;
import com.google.api.services.cloudkms.v1beta1.model.UpdateCryptoKeyPrimaryVersionRequest; import com.google.api.services.cloudkms.v1beta1.model.UpdateCryptoKeyPrimaryVersionRequest;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeSleeper;
import google.registry.util.Retrier;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -69,6 +72,8 @@ public class KmsConnectionImplTest {
@Mock private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.Encrypt kmsCryptoKeysEncrypt; @Mock private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.Encrypt kmsCryptoKeysEncrypt;
@Mock private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.Decrypt kmsCryptoKeysDecrypt; @Mock private CloudKMS.Projects.Locations.KeyRings.CryptoKeys.Decrypt kmsCryptoKeysDecrypt;
private final Retrier retrier = new Retrier(new FakeSleeper(new FakeClock()), 3);
@Captor private ArgumentCaptor<KeyRing> keyRing; @Captor private ArgumentCaptor<KeyRing> keyRing;
@Captor private ArgumentCaptor<CryptoKey> cryptoKey; @Captor private ArgumentCaptor<CryptoKey> cryptoKey;
@Captor private ArgumentCaptor<CryptoKeyVersion> cryptoKeyVersion; @Captor private ArgumentCaptor<CryptoKeyVersion> cryptoKeyVersion;
@ -116,7 +121,7 @@ public class KmsConnectionImplTest {
public void test_encrypt_createsKeyRingIfNotFound() throws Exception { public void test_encrypt_createsKeyRingIfNotFound() throws Exception {
when(kmsKeyRingsGet.execute()).thenThrow(createNotFoundException()); when(kmsKeyRingsGet.execute()).thenThrow(createNotFoundException());
new KmsConnectionImpl("foo", "bar", kms).encrypt("key", "moo".getBytes(UTF_8)); new KmsConnectionImpl("foo", "bar", retrier, kms).encrypt("key", "moo".getBytes(UTF_8));
verify(kmsKeyRings).create(locationName.capture(), keyRing.capture()); verify(kmsKeyRings).create(locationName.capture(), keyRing.capture());
assertThat(locationName.getValue()).isEqualTo("projects/foo/locations/global"); assertThat(locationName.getValue()).isEqualTo("projects/foo/locations/global");
@ -135,7 +140,7 @@ public class KmsConnectionImplTest {
public void test_encrypt_newCryptoKey() throws Exception { public void test_encrypt_newCryptoKey() throws Exception {
when(kmsCryptoKeysGet.execute()).thenThrow(createNotFoundException()); when(kmsCryptoKeysGet.execute()).thenThrow(createNotFoundException());
new KmsConnectionImpl("foo", "bar", kms).encrypt("key", "moo".getBytes(UTF_8)); new KmsConnectionImpl("foo", "bar", retrier, kms).encrypt("key", "moo".getBytes(UTF_8));
verify(kmsCryptoKeys).create(keyRingName.capture(), cryptoKey.capture()); verify(kmsCryptoKeys).create(keyRingName.capture(), cryptoKey.capture());
assertThat(keyRingName.getValue()).isEqualTo("projects/foo/locations/global/keyRings/bar"); assertThat(keyRingName.getValue()).isEqualTo("projects/foo/locations/global/keyRings/bar");
@ -154,7 +159,7 @@ public class KmsConnectionImplTest {
@Test @Test
public void test_encrypt() throws Exception { public void test_encrypt() throws Exception {
new KmsConnectionImpl("foo", "bar", kms).encrypt("key", "moo".getBytes(UTF_8)); new KmsConnectionImpl("foo", "bar", retrier, kms).encrypt("key", "moo".getBytes(UTF_8));
verify(kmsCryptoKeyVersions).create(cryptoKeyName.capture(), cryptoKeyVersion.capture()); verify(kmsCryptoKeyVersions).create(cryptoKeyName.capture(), cryptoKeyVersion.capture());
@ -182,7 +187,7 @@ public class KmsConnectionImplTest {
when(kmsCryptoKeysDecrypt.execute()) when(kmsCryptoKeysDecrypt.execute())
.thenReturn(new DecryptResponse().encodePlaintext("moo".getBytes(UTF_8))); .thenReturn(new DecryptResponse().encodePlaintext("moo".getBytes(UTF_8)));
byte[] plaintext = new KmsConnectionImpl("foo", "bar", kms).decrypt("key", "blah"); byte[] plaintext = new KmsConnectionImpl("foo", "bar", retrier, kms).decrypt("key", "blah");
verify(kmsCryptoKeys).decrypt(cryptoKeyName.capture(), decryptRequest.capture()); verify(kmsCryptoKeys).decrypt(cryptoKeyName.capture(), decryptRequest.capture());
assertThat(cryptoKeyName.getValue()) assertThat(cryptoKeyName.getValue())