Skip to content

Commit c191cd5

Browse files
authored
Add aws default credentials provider (#3842)
1 parent 205252d commit c191cd5

4 files changed

Lines changed: 63 additions & 15 deletions

File tree

docs/application-settings.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@ The general idea is that you'll place all the account-specific settings in a sep
277277
```yaml
278278
settings:
279279
s3:
280-
accessKeyId: <S3 access key>
281-
secretAccessKey: <S3 access key>
280+
accessKeyId: <S3 access key> # optional
281+
secretAccessKey: <S3 access key> #optional
282282
endpoint: <endpoint> # http://s3.storage.com
283283
bucket: <bucket name> # prebid-application-settings
284284
region: <region name> # if not provided AWS_GLOBAL will be used. Example value: 'eu-central-1'
@@ -298,6 +298,14 @@ settings:
298298
timeout: 5000
299299
```
300300
301+
If `accessKeyId` and `secretAccessKey` are not specified in the Prebid Server configuration then AWS credentials will be looked up in this order:
302+
- Java System Properties - `aws.accessKeyId` and `aws.secretAccessKey`
303+
- Environment Variables - `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
304+
- Web Identity Token credentials from system properties or environment variables
305+
- Credential profiles file at the default location (`~/.aws/credentials`) shared by all AWS SDKs and the AWS CLI
306+
- Credentials delivered through the Amazon EC2 container service if "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" environment variable is set and security manager has permission to access the variable,
307+
- Instance profile credentials delivered through the Amazon EC2 metadata service
308+
301309
### File format
302310

303311
We recommend using the `json` format for your account configuration. A minimal configuration may look like this.

docs/config-app.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,8 @@ contain 'WHERE last_updated > ?' for MySQL and 'WHERE last_updated > $1' for Pos
391391

392392
For S3 storage configuration
393393
- `settings.in-memory-cache.s3-update.refresh-rate` - refresh period in ms for stored request updates in S3
394-
- `settings.s3.access-key-id` - an access key
395-
- `settings.s3.secret-access-key` - a secret access key
394+
- `settings.s3.access-key-id` - an access key (optional)
395+
- `settings.s3.secret-access-key` - a secret access key (optional)
396396
- `settings.s3.region` - a region, AWS_GLOBAL by default
397397
- `settings.s3.endpoint` - an endpoint
398398
- `settings.s3.bucket` - a bucket name
@@ -402,6 +402,15 @@ For S3 storage configuration
402402
- `settings.s3.stored-requests-dir` - a directory with stored requests
403403
- `settings.s3.stored-responses-dir` - a directory with stored responses
404404

405+
If `settings.s3.access-key-id` and `settings.s3.secret-access-key` are not specified in the Prebid Server configuration then AWS credentials will be looked up in this order:
406+
- Java System Properties - `aws.accessKeyId` and `aws.secretAccessKey`
407+
- Environment Variables - `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
408+
- Web Identity Token credentials from system properties or environment variables
409+
- Credential profiles file at the default location (`~/.aws/credentials`) shared by all AWS SDKs and the AWS CLI
410+
- Credentials delivered through the Amazon EC2 container service if "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" environment variable is set and security manager has permission to access the variable,
411+
- Instance profile credentials delivered through the Amazon EC2 metadata service
412+
413+
405414
For targeting available next options:
406415
- `settings.targeting.truncate-attr-chars` - set the max length for names of targeting keywords (0 means no truncation).
407416

src/main/java/org/prebid/server/spring/config/SettingsConfiguration.java

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.prebid.server.spring.config;
22

3+
import org.apache.commons.lang3.StringUtils;
4+
import org.prebid.server.log.Logger;
5+
import org.prebid.server.log.LoggerFactory;
36
import io.vertx.core.Vertx;
47
import io.vertx.core.file.FileSystem;
58
import lombok.Data;
@@ -40,9 +43,12 @@
4043
import org.springframework.stereotype.Component;
4144
import org.springframework.validation.annotation.Validated;
4245
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
46+
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
4347
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
48+
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
4449
import software.amazon.awssdk.regions.Region;
4550
import software.amazon.awssdk.services.s3.S3AsyncClient;
51+
import software.amazon.awssdk.core.exception.SdkClientException;
4652

4753
import javax.validation.constraints.Min;
4854
import javax.validation.constraints.NotBlank;
@@ -58,6 +64,8 @@
5864
@UtilityClass
5965
public class SettingsConfiguration {
6066

67+
private static final Logger logger = LoggerFactory.getLogger(SettingsConfiguration.class);
68+
6169
@Configuration
6270
@ConditionalOnProperty(prefix = "settings.filesystem",
6371
name = {"settings-filename", "stored-requests-dir", "stored-imps-dir"})
@@ -233,18 +241,30 @@ static class S3SettingsConfiguration {
233241

234242
@Component
235243
@ConfigurationProperties(prefix = "settings.s3")
236-
@ConditionalOnProperty(prefix = "settings.s3", name = {"accessKeyId", "secretAccessKey"})
237244
@Validated
238245
@Data
239246
@NoArgsConstructor
240247
protected static class S3ConfigurationProperties {
241248

242-
@NotBlank
249+
/**
250+
* If accessKeyId and secretAccessKey are provided in the
251+
* configuration file then they will be used. Otherwise, the
252+
* DefaultCredentialsProvider will look for credentials in this order:
253+
*
254+
* - Java System Properties
255+
* - Environment Variables
256+
* - Web Identity Token
257+
* - AWS credentials file (~/.aws/credentials)
258+
* - ECS container credentials
259+
* - EC2 instance profile
260+
*/
243261
private String accessKeyId;
244-
245-
@NotBlank
246262
private String secretAccessKey;
247263

264+
private boolean useStaticCredentials() {
265+
return StringUtils.isNotBlank(accessKeyId) && StringUtils.isNotBlank(secretAccessKey);
266+
}
267+
248268
/**
249269
* If not provided AWS_GLOBAL will be used as a region
250270
*/
@@ -274,22 +294,33 @@ protected static class S3ConfigurationProperties {
274294

275295
@Bean
276296
S3AsyncClient s3AsyncClient(S3ConfigurationProperties s3ConfigurationProperties) throws URISyntaxException {
277-
final AwsBasicCredentials credentials = AwsBasicCredentials.create(
278-
s3ConfigurationProperties.getAccessKeyId(),
279-
s3ConfigurationProperties.getSecretAccessKey());
280297
final Region awsRegion = Optional.ofNullable(s3ConfigurationProperties.getRegion())
281298
.map(Region::of)
282299
.orElse(Region.AWS_GLOBAL);
283300

284-
return S3AsyncClient
285-
.builder()
286-
.credentialsProvider(StaticCredentialsProvider.create(credentials))
301+
return S3AsyncClient.builder()
302+
.credentialsProvider(awsCredentialsProvider(s3ConfigurationProperties))
287303
.endpointOverride(new URI(s3ConfigurationProperties.getEndpoint()))
288304
.forcePathStyle(s3ConfigurationProperties.getForcePathStyle())
289305
.region(awsRegion)
290306
.build();
291307
}
292308

309+
private static AwsCredentialsProvider awsCredentialsProvider(S3ConfigurationProperties config) {
310+
final AwsCredentialsProvider credentialsProvider = config.useStaticCredentials()
311+
? StaticCredentialsProvider.create(
312+
AwsBasicCredentials.create(config.getAccessKeyId(), config.getSecretAccessKey()))
313+
: DefaultCredentialsProvider.create();
314+
315+
try {
316+
credentialsProvider.resolveCredentials();
317+
} catch (SdkClientException e) {
318+
logger.error("Failed to resolve AWS credentials", e);
319+
}
320+
321+
return credentialsProvider;
322+
}
323+
293324
@Bean
294325
S3ApplicationSettings s3ApplicationSettings(S3AsyncClient s3AsyncClient,
295326
S3ConfigurationProperties s3ConfigurationProperties,

src/test/java/org/prebid/server/hooks/execution/HookStageExecutorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ public void shouldExecuteEntrypointHooksToleratingTimeoutAndFailedFuture(VertxTe
654654
assertThat(hookOutcome.getStatus())
655655
.isEqualTo(ExecutionStatus.execution_failure);
656656
assertThat(hookOutcome.getMessage()).isEqualTo("Failed after a while");
657-
assertThat(hookOutcome.getExecutionTime()).isBetween(50L, 70L);
657+
assertThat(hookOutcome.getExecutionTime()).isBetween(50L, 80L);
658658
});
659659

660660
assertThat(group0Hooks.get(1)).satisfies(hookOutcome -> {

0 commit comments

Comments
 (0)