-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
307 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package bg.kidsground.config; | ||
|
||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.context.annotation.Lazy; | ||
import org.springframework.core.Ordered; | ||
import org.springframework.core.annotation.Order; | ||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; | ||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain; | ||
import software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider; | ||
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; | ||
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; | ||
import software.amazon.awssdk.regions.Region; | ||
import software.amazon.awssdk.services.ssm.SsmClient; | ||
|
||
|
||
@Order(Ordered.HIGHEST_PRECEDENCE) | ||
@Configuration | ||
public class AwsConfig { | ||
|
||
private final String appName = "kidsground"; | ||
|
||
@Lazy(false) | ||
@Bean | ||
public AwsParameterBeanPostProcessor setupAwsParamBeanPostProcessor(SsmClient ssmClient) { | ||
AwsParameterBeanPostProcessor beanPostProcessor = new AwsParameterBeanPostProcessor(ssmClient, appName); | ||
return beanPostProcessor; | ||
} | ||
|
||
@Bean | ||
public AwsCredentialsProvider awsCredentialsProvider(@Value("${aws.app.name:}") String awsCredentialProfileName) { | ||
if (awsCredentialProfileName != null && !awsCredentialProfileName.isBlank()) { | ||
final ProfileCredentialsProvider create = ProfileCredentialsProvider.create(awsCredentialProfileName); | ||
return AwsCredentialsProviderChain.builder() | ||
.addCredentialsProvider(create) | ||
.addCredentialsProvider(InstanceProfileCredentialsProvider.create()) | ||
.build(); | ||
} | ||
return AwsCredentialsProviderChain.builder() | ||
.addCredentialsProvider(InstanceProfileCredentialsProvider.create()) | ||
.build(); | ||
} | ||
|
||
@Lazy(false) | ||
@Bean | ||
@ConditionalOnBean(value = AwsCredentialsProvider.class) | ||
public SsmClient ssmClient(AwsCredentialsProvider awsCredentialsProvider) { | ||
return SsmClient.builder() | ||
.credentialsProvider(awsCredentialsProvider) | ||
.region(Region.EU_CENTRAL_1) | ||
.httpClient(UrlConnectionHttpClient.builder().build()) | ||
.build(); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
backend/src/main/java/bg/kidsground/config/AwsParameter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package bg.kidsground.config; | ||
|
||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Target({ElementType.FIELD}) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Documented | ||
public @interface AwsParameter { | ||
String value(); | ||
} |
103 changes: 103 additions & 0 deletions
103
backend/src/main/java/bg/kidsground/config/AwsParameterBeanPostProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package bg.kidsground.config; | ||
|
||
import jakarta.annotation.PostConstruct; | ||
import java.lang.reflect.Field; | ||
import java.util.Optional; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.BeansException; | ||
import org.springframework.beans.factory.config.BeanPostProcessor; | ||
import org.springframework.context.EnvironmentAware; | ||
import org.springframework.core.env.Environment; | ||
import org.springframework.util.ReflectionUtils; | ||
import software.amazon.awssdk.core.exception.SdkException; | ||
import software.amazon.awssdk.services.ssm.SsmClient; | ||
import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest; | ||
import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse; | ||
import software.amazon.awssdk.services.ssm.model.Parameter; | ||
|
||
public class AwsParameterBeanPostProcessor implements BeanPostProcessor, EnvironmentAware { | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(AwsParameterBeanPostProcessor.class); | ||
private final String appName; | ||
private Environment environment; | ||
private SsmClient ssmClient; | ||
private GetParametersByPathResponse applicationParams; | ||
|
||
public AwsParameterBeanPostProcessor(SsmClient ssmClient, String appName) { | ||
this.ssmClient = ssmClient; | ||
this.appName = appName; | ||
} | ||
|
||
@PostConstruct | ||
public void init() { | ||
if (ssmClient == null) { | ||
LOG.warn("application cannot be injected with aws ssm parameters without ssmClient."); | ||
} | ||
if (appName == null || appName.isBlank()) { | ||
LOG.warn("application cannot be injected with aws ssm parameters without setting the 'aws.app.name' property."); | ||
} | ||
if (ssmClient != null) { | ||
try { | ||
GetParametersByPathRequest byPathRequest = GetParametersByPathRequest.builder().path( "/config/" + appName + "/").build(); | ||
applicationParams = ssmClient.getParametersByPath(byPathRequest); | ||
} catch (SdkException e) { | ||
LOG.warn("Unable to retrieve parameters from SSM due to exception: {}", e.getMessage()); | ||
LOG.warn("Parameter injection from SSM will not be possible due to an error communicating with the service. Please check permissions."); | ||
LOG.warn("Parameter injection will only occur through properties and environment variables"); | ||
ssmClient = null; | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void setEnvironment(Environment environment) { | ||
this.environment = environment; | ||
} | ||
|
||
@Override | ||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { | ||
// instrospec the bean for fields with AwsParameter annotation | ||
Class<?> clazz = bean.getClass(); | ||
// only scan beans in this package | ||
if (clazz.getName().startsWith("bg.kidsground")) { | ||
Field[] fields = clazz.getDeclaredFields(); | ||
for (Field field : fields) { | ||
if (field.isAnnotationPresent(AwsParameter.class)) { | ||
ReflectionUtils.makeAccessible(field); | ||
AwsParameter awsParameter = field.getAnnotation(AwsParameter.class); | ||
String annotationValue = awsParameter.value(); | ||
String[] split = annotationValue.split(":"); | ||
String paramName = split[0]; | ||
String defaultValue = split.length > 1 ? split[1] : null; | ||
|
||
if (applicationParams != null) { | ||
Optional<Parameter> valueForField = applicationParams.parameters().stream().filter(param -> param.name().contains(paramName)).findFirst(); | ||
if (valueForField.isPresent()) { | ||
LOG.info("Injecting value for field {} into bean {}", paramName, bean.getClass().getCanonicalName()); | ||
final String value = valueForField.get().value(); | ||
setField(field, bean, value); | ||
continue; | ||
} | ||
} | ||
Object property = environment.getProperty(paramName, field.getType()); | ||
if (property != null) { | ||
setField(field, bean, property); | ||
} else if (defaultValue != null) { | ||
setField(field, bean, defaultValue); | ||
} | ||
} | ||
} | ||
} | ||
return bean; | ||
} | ||
|
||
private void setField(Field field, Object bean, Object value) { | ||
try { | ||
field.set(bean, value); | ||
} catch (IllegalArgumentException | IllegalAccessException ex) { | ||
LOG.error(ex.getMessage(), ex); | ||
} | ||
} | ||
|
||
} |
33 changes: 33 additions & 0 deletions
33
backend/src/main/java/bg/kidsground/config/DataSourceConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package bg.kidsground.config; | ||
|
||
import bg.kidsground.service.SecretsService; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.context.annotation.Primary; | ||
import org.springframework.jdbc.datasource.DriverManagerDataSource; | ||
|
||
import javax.sql.DataSource; | ||
|
||
@Configuration | ||
public class DataSourceConfig { | ||
|
||
final SecretsService secretsService; | ||
|
||
@Autowired | ||
public DataSourceConfig(SecretsService secretsService) { | ||
this.secretsService = secretsService; | ||
} | ||
|
||
@Primary | ||
@Bean | ||
public DataSource dataSource() { | ||
|
||
DriverManagerDataSource dataSource = new DriverManagerDataSource(); | ||
dataSource.setUrl(this.secretsService.getSecret("db.url")); | ||
dataSource.setUsername(this.secretsService.getSecret("db.username")); | ||
dataSource.setPassword(this.secretsService.getSecret("db.password")); | ||
|
||
return dataSource; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
backend/src/main/java/bg/kidsground/controller/SecretsController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package bg.kidsground.controller; | ||
|
||
import bg.kidsground.constants.AppRestEndpoints; | ||
import bg.kidsground.service.SecretsService; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
public class SecretsController { | ||
@Autowired | ||
private SecretsService secretsService; | ||
|
||
@GetMapping(AppRestEndpoints.V1.Secrets.MAPS_API_KEY) | ||
public ResponseEntity<String> getMapsApiKey() { | ||
return ResponseEntity.ok(this.secretsService.getSecret("maps.apiKey")); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
backend/src/main/java/bg/kidsground/service/SecretsService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package bg.kidsground.service; | ||
|
||
public interface SecretsService { | ||
String getSecret(String name); | ||
} |
27 changes: 27 additions & 0 deletions
27
backend/src/main/java/bg/kidsground/service/SecretsServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package bg.kidsground.service; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Service; | ||
import software.amazon.awssdk.services.ssm.SsmClient; | ||
import software.amazon.awssdk.services.ssm.model.GetParameterRequest; | ||
|
||
@Service | ||
@Slf4j | ||
public class SecretsServiceImpl implements SecretsService { | ||
|
||
@Autowired | ||
private SsmClient ssmClient; | ||
|
||
public String getSecret(String secretName) { | ||
String secret = this.ssmClient.getParameter( | ||
GetParameterRequest.builder() | ||
.name("/config/kidsground/" + secretName) | ||
.withDecryption(true) | ||
.build()) | ||
.parameter() | ||
.value(); | ||
log.info("got secret from param store with name {} and value {}", secretName, secret); | ||
return secret; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
server.port=8009 | ||
spring.h2.console.enabled=true | ||
spring.datasource.url=jdbc:h2:mem:testdb | ||
spring.datasource.driver-class-name=org.h2.Driver | ||
spring.datasource.username=sa | ||
spring.datasource.password=admin | ||
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect | ||
spring.datasource.driver-class-name=org.postgresql.Driver | ||
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect | ||
spring.jpa.hibernate.ddl-auto=update | ||
spring.jpa.show-sql=true | ||
|
||
security.basic.enable=false | ||
security.ignored=/** | ||
security.ignored=/** | ||
|
||
spring.application.name=kidsground | ||
cloud.aws.region.static=eu-central-1 | ||
|
||
aws.app.name=kidsground |