Skip to content

Commit

Permalink
#245 Refactor & extract GCP secrets service from H2 data src (#246)
Browse files Browse the repository at this point in the history
* #245 Refactor & extract GCP secrets service from H2 data src

* #245 Update build.gradle

* #245 Update IronocDbConfigTest.java
  • Loading branch information
conorheffron authored Sep 26, 2024
1 parent d7dff90 commit 5eea677
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 43 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ apply plugin: 'war'
apply plugin: 'maven-publish'

group = 'conorheffron'
version = '5.2.1'
version = '5.2.2'
description = "Sample Data Manager"

sourceCompatibility = 21
Expand Down
21 changes: 5 additions & 16 deletions src/main/java/com/ironoc/db/config/IronocDbConfig.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.ironoc.db.config;

import com.google.cloud.secretmanager.v1.AccessSecretVersionResponse;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
import com.ironoc.db.enums.DataSourceKey;
import com.ironoc.db.service.GoogleCloudClient;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -22,25 +21,15 @@ public class IronocDbConfig {

@Bean
@Profile("h2")
public DataSource dataSource(@Autowired Environment environment) {
@Autowired
public DataSource dataSource(Environment environment, GoogleCloudClient googleCloudClient) {
DataSourceBuilder dsBuilder = DataSourceBuilder.create();
dsBuilder.driverClassName(environment.getRequiredProperty(DataSourceKey.DRIVER_CLASS_NAME.getKey()));
dsBuilder.url(environment.getRequiredProperty(DataSourceKey.DS_URL.getKey()));
dsBuilder.username(environment.getRequiredProperty(DataSourceKey.DS_USERNAME.getKey()));
dsBuilder.password(getDataSourceSecret(environment.getRequiredProperty(DataSourceKey.GCP_SEC_VER.getKey())));
dsBuilder.password(googleCloudClient.getSecret(environment.getRequiredProperty(
DataSourceKey.GCP_SEC_VER.getKey())));
dsBuilder.type(HikariDataSource.class);
return dsBuilder.build();
}

private String getDataSourceSecret(String secretVersion) {
String secretValue = "";
try {
SecretManagerServiceClient client = SecretManagerServiceClient.create();
AccessSecretVersionResponse response = client.accessSecretVersion(secretVersion);
secretValue = response.getPayload().getData().toStringUtf8();
} catch (Exception e) {
log.error("Unexpected error occurred extracting GCP secret.", e);
}
return secretValue;
}
}
5 changes: 5 additions & 0 deletions src/main/java/com/ironoc/db/service/GoogleCloudClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.ironoc.db.service;

public interface GoogleCloudClient {
String getSecret(String secretVersion);
}
27 changes: 27 additions & 0 deletions src/main/java/com/ironoc/db/service/GoogleCloudClientImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.ironoc.db.service;

import com.google.cloud.secretmanager.v1.AccessSecretVersionResponse;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class GoogleCloudClientImpl implements GoogleCloudClient {

@Override
public String getSecret(String secretVersion) {
String secretValue = "";
try {
SecretManagerServiceClient client = SecretManagerServiceClient.create();
AccessSecretVersionResponse response = client.accessSecretVersion(secretVersion);
secretValue = response.getPayload().getData().toStringUtf8();
log.info("Extracting GCP secret key={}", secretVersion);
} catch (Exception e) {
log.error("Unexpected error occurred extracting GCP secret.", e);
}
return secretValue;
}
}
49 changes: 23 additions & 26 deletions src/test/java/com/ironoc/db/config/IronocDbConfigTest.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.ironoc.db.config;

import com.google.cloud.secretmanager.v1.AccessSecretVersionResponse;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
import com.google.cloud.secretmanager.v1.SecretPayload;
import com.google.protobuf.ByteString;
import com.ironoc.db.enums.DataSourceKey;
import com.ironoc.db.service.GoogleCloudClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
Expand All @@ -16,8 +16,6 @@

import javax.sql.DataSource;

import java.io.IOException;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.hamcrest.Matchers.is;
Expand All @@ -42,42 +40,41 @@ public class IronocDbConfigTest {
private DataSource dataSourceMock;

@Mock
private AccessSecretVersionResponse accessSecretVersionResponseMock;

@Mock
private SecretManagerServiceClient secretManagerServiceClientMock;

@Mock
private SecretPayload secretPayloadMock;
private GoogleCloudClient googleCloudClientMock;

// Static mocks
private MockedStatic<DataSourceBuilder> dataSourceBuilderMockedStatic = mockStatic(DataSourceBuilder.class);

private MockedStatic<SecretManagerServiceClient> secretManagerServiceClientMockedStatic =
mockStatic(SecretManagerServiceClient.class);

private static final String TEST_SECRET_KEY = "projects/123/secrets/<TEST_SECRET_NAME>/versions/33";
private static final String TEST_SECRET_DATA = "TeSt_SeCr3t_V0l";

@Before
public void setUp() {
BDDMockito.given(DataSourceBuilder.create()).willReturn(dataSourceBuilderMock);
}

@After
public void tearDown() {
dataSourceBuilderMockedStatic.close();
}

@Test
public void test_error_view_success() throws IOException {
public void test_dataSource_success() {
// given
when(environmentMock.getRequiredProperty(anyString())).thenReturn(new String());
BDDMockito.given(DataSourceBuilder.create()).willReturn(dataSourceBuilderMock);
when(environmentMock.getRequiredProperty(DataSourceKey.GCP_SEC_VER.getKey())).thenReturn(TEST_SECRET_KEY);
when(dataSourceBuilderMock.build()).thenReturn(dataSourceMock);
BDDMockito.given(SecretManagerServiceClient.create()).willReturn(secretManagerServiceClientMock);
when(secretManagerServiceClientMock.accessSecretVersion(anyString())).thenReturn(accessSecretVersionResponseMock);
when(accessSecretVersionResponseMock.getPayload()).thenReturn(secretPayloadMock);
when(secretPayloadMock.getData()).thenReturn(ByteString.copyFromUtf8(TEST_SECRET_DATA));
when(googleCloudClientMock.getSecret(TEST_SECRET_KEY)).thenReturn(TEST_SECRET_DATA);

// when
DataSource result = ironocDbConfig.dataSource(environmentMock);
DataSource result = ironocDbConfig.dataSource(environmentMock, googleCloudClientMock);

// then
dataSourceBuilderMockedStatic.verify(() -> DataSourceBuilder.create());
verify(environmentMock).getRequiredProperty(DataSourceKey.GCP_SEC_VER.getKey());
verify(environmentMock, times(4)).getRequiredProperty(anyString());
verify(dataSourceBuilderMock).build();
verify(secretManagerServiceClientMock).accessSecretVersion(anyString());
verify(accessSecretVersionResponseMock).getPayload();
verify(secretPayloadMock).getData();
verify(googleCloudClientMock).getSecret(TEST_SECRET_KEY);

assertThat(result, is(dataSourceMock));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.ironoc.db.service;

import com.google.cloud.secretmanager.v1.AccessSecretVersionResponse;
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
import com.google.cloud.secretmanager.v1.SecretPayload;
import com.google.protobuf.ByteString;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.MockitoJUnitRunner;

import java.io.IOException;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.emptyString;
import static org.mockito.ArgumentMatchers.anyString;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.doThrow;

@RunWith(MockitoJUnitRunner.Silent.class)
public class GoogleCloudClientServiceTest {

@InjectMocks
private GoogleCloudClientImpl googleCloudClient;

@Mock
private AccessSecretVersionResponse accessSecretVersionResponseMock;

@Mock
private SecretPayload secretPayloadMock;

@Mock
private SecretManagerServiceClient secretManagerServiceClientMock;

private MockedStatic<SecretManagerServiceClient> secretManagerServiceClientMockedStatic =
mockStatic(SecretManagerServiceClient.class);

private static final String TEST_SECRET_DATA = "TeSt_SeCr3t_V0l";
private static final String TEST_SECRET_KEY = "projects/123/secrets/<TEST_SECRET_NAME>/versions/33";

@Before
public void setUp() throws IOException {
BDDMockito.given(SecretManagerServiceClient.create()).willReturn(secretManagerServiceClientMock);
}

@After
public void tearDown() {
secretManagerServiceClientMockedStatic.close();
}

@Test
public void test_getSecret_success() {
// given
when(secretManagerServiceClientMock.accessSecretVersion(anyString()))
.thenReturn(accessSecretVersionResponseMock);
when(accessSecretVersionResponseMock.getPayload()).thenReturn(secretPayloadMock);
when(secretPayloadMock.getData()).thenReturn(ByteString.copyFromUtf8(TEST_SECRET_DATA));

// when
String result = googleCloudClient.getSecret(TEST_SECRET_KEY);

// then
secretManagerServiceClientMockedStatic.verify(() -> SecretManagerServiceClient.create());
verify(secretManagerServiceClientMock).accessSecretVersion(anyString());
verify(accessSecretVersionResponseMock).getPayload();
verify(secretPayloadMock).getData();

assertThat(result, is(TEST_SECRET_DATA));
}

@Test
public void test_getSecret_fail() {
// given
doThrow(new UnsupportedOperationException("test exception."))
.when(secretManagerServiceClientMock).accessSecretVersion(TEST_SECRET_KEY);

// when
String result = googleCloudClient.getSecret(TEST_SECRET_KEY);

// then
secretManagerServiceClientMockedStatic.verify(() -> SecretManagerServiceClient.create());
verify(secretManagerServiceClientMock).accessSecretVersion(anyString());
verify(accessSecretVersionResponseMock, never()).getPayload();
verify(secretPayloadMock, never()).getData();

assertThat(result, is(emptyString()));
}
}

0 comments on commit 5eea677

Please sign in to comment.