Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Healthcheck status for keys loading #738

Merged
merged 24 commits into from
Mar 24, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d42a1c2
wip
usmansaleem Mar 13, 2023
26e7937
Merge remote-tracking branch 'upstream/master' into healthcheck
usmansaleem Mar 14, 2023
6c7c1c0
Add healthcheck for key loading - aws bulk load
usmansaleem Mar 14, 2023
810c226
Fix healthckeck order
usmansaleem Mar 15, 2023
3cb3c3c
aws AT - healthcheck
usmansaleem Mar 15, 2023
030c39b
azure bulk load healthcheck
usmansaleem Mar 15, 2023
941b3d6
add healthcheck assertion for azure AT
usmansaleem Mar 15, 2023
0aa4aad
Add healthcheck for bulk loading keystores
usmansaleem Mar 16, 2023
8983d51
Add healthcheck for keys loaded from config files
usmansaleem Mar 16, 2023
a3f49b2
healthcheck for unexpected signers failure
usmansaleem Mar 16, 2023
6c61244
Merge remote-tracking branch 'upstream/master' into healthcheck
usmansaleem Mar 22, 2023
ef8214c
review suggestions - use reduce method and simplified static methods
usmansaleem Mar 22, 2023
8d9aeb2
blskeystore bulk loader - reduce logic
usmansaleem Mar 22, 2023
498940d
review suggestion - refactor register healthcheck for signer loader
usmansaleem Mar 22, 2023
ea83580
error count if config file doesnt exist
usmansaleem Mar 22, 2023
d2e47c2
review suggestion - Azure AT, healthcheck UP
usmansaleem Mar 22, 2023
1dc4da1
[SKIP-CI] Changelog
usmansaleem Mar 23, 2023
07f914e
[SKIP-CI] Fix versions.gradle merge conflict
usmansaleem Mar 23, 2023
31f2441
review suggestion - MappedResults
usmansaleem Mar 23, 2023
13f3dc5
Using published version of signers
usmansaleem Mar 23, 2023
4aa854c
Aws Secrets Manager bulk loading AT - Add invalid cred healthcheck
usmansaleem Mar 24, 2023
3b335e2
healthcheck AT for config-file-loading
usmansaleem Mar 24, 2023
6fb1f29
healthcheck AT for config-file-loading
usmansaleem Mar 24, 2023
e15472a
Merge remote-tracking branch 'upstream/master' into healthcheck
usmansaleem Mar 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog

## Upcoming version
### Features Added
- Enhanced Healthcheck endpoint reporting status of loading of signers keys [#738](https://github.com/ConsenSys/web3signer/pull/738)
- Optional AWS endpoint overriding for bulk loading `--aws-endpoint-override`. Useful for local testing against localstack. [#730](https://github.com/ConsenSys/web3signer/issues/730)

### Bugs Fixed
- Update of Azure libraries (transitive via signers library) and manual override to fix CVE-2023-1370

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public class Signer extends FilecoinJsonRpcEndpoint {
public static final ObjectMapper ETH_2_INTERFACE_OBJECT_MAPPER =
SigningObjectMapperFactory.createObjectMapper().setSerializationInclusion(Include.NON_NULL);
private static final String METRICS_ENDPOINT = "/metrics";
private static final String HEALTHCHECK_ENDPOINT = "/healthcheck";

private final SignerConfiguration signerConfig;
private final Web3SignerRunner runner;
Expand Down Expand Up @@ -185,4 +186,8 @@ public String getSlashingDbUrl() {
public Response callReload() {
return given().baseUri(getUrl()).post(RELOAD_ENDPOINT);
}

public Response healthcheck() {
return given().baseUri(getUrl()).get(HEALTHCHECK_ENDPOINT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package tech.pegasys.web3signer.dsl.signer.runner;

import static tech.pegasys.web3signer.commandline.PicoCliAwsSecretsManagerParameters.AWS_ENDPOINT_OVERRIDE_OPTION;
import static tech.pegasys.web3signer.commandline.PicoCliAwsSecretsManagerParameters.AWS_SECRETS_ACCESS_KEY_ID_OPTION;
import static tech.pegasys.web3signer.commandline.PicoCliAwsSecretsManagerParameters.AWS_SECRETS_AUTH_MODE_OPTION;
import static tech.pegasys.web3signer.commandline.PicoCliAwsSecretsManagerParameters.AWS_SECRETS_ENABLED_OPTION;
Expand Down Expand Up @@ -422,6 +423,16 @@ private String awsBulkLoadingOptions(
String.join(",", awsSecretsManagerParameters.getTagValuesFilter())));
}

awsSecretsManagerParameters
.getEndpointOverride()
.ifPresent(
uri ->
yamlConfig.append(
String.format(
YAML_STRING_FMT,
"eth2." + AWS_ENDPOINT_OVERRIDE_OPTION.substring(2),
uri)));

return yamlConfig.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package tech.pegasys.web3signer.dsl.signer.runner;

import static tech.pegasys.web3signer.commandline.PicoCliAwsSecretsManagerParameters.AWS_ENDPOINT_OVERRIDE_OPTION;
import static tech.pegasys.web3signer.commandline.PicoCliAwsSecretsManagerParameters.AWS_SECRETS_ACCESS_KEY_ID_OPTION;
import static tech.pegasys.web3signer.commandline.PicoCliAwsSecretsManagerParameters.AWS_SECRETS_AUTH_MODE_OPTION;
import static tech.pegasys.web3signer.commandline.PicoCliAwsSecretsManagerParameters.AWS_SECRETS_ENABLED_OPTION;
Expand Down Expand Up @@ -255,6 +256,14 @@ private Collection<String> awsBulkLoadingOptions(
params.add(awsSecretsManagerParameters.getRegion());
}

awsSecretsManagerParameters
.getEndpointOverride()
.ifPresent(
uri -> {
params.add(AWS_ENDPOINT_OVERRIDE_OPTION);
params.add(uri.toString());
});

if (!awsSecretsManagerParameters.getPrefixesFilter().isEmpty()) {
params.add(AWS_SECRETS_PREFIXES_FILTER_OPTION);
params.add(String.join(",", awsSecretsManagerParameters.getPrefixesFilter()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package tech.pegasys.web3signer.tests.bulkloading;

import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;

import tech.pegasys.teku.bls.BLSKeyPair;
Expand All @@ -24,6 +25,7 @@
import tech.pegasys.web3signer.signing.config.AwsSecretsManagerParametersBuilder;
import tech.pegasys.web3signer.tests.AcceptanceTestBase;

import java.net.URI;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -69,13 +71,20 @@ public class AwsSecretsManagerAcceptanceTest extends AcceptanceTestBase {
private static final String RO_AWS_SECRET_ACCESS_KEY = System.getenv("AWS_SECRET_ACCESS_KEY");
private static final String AWS_REGION =
Optional.ofNullable(System.getenv("AWS_REGION")).orElse("us-east-2");

// can be pointed to localstack
private final Optional<URI> awsEndpointOverride =
System.getenv("AWS_ENDPOINT_OVERRIDE") != null
? Optional.of(URI.create(System.getenv("AWS_ENDPOINT_OVERRIDE")))
: Optional.empty();
private AwsSecretsManagerUtil awsSecretsManagerUtil;
private final List<BLSKeyPair> blsKeyPairs = new ArrayList<>();

@BeforeAll
void setupAwsResources() {
awsSecretsManagerUtil =
new AwsSecretsManagerUtil(AWS_REGION, RW_AWS_ACCESS_KEY_ID, RW_AWS_SECRET_ACCESS_KEY);
new AwsSecretsManagerUtil(
AWS_REGION, RW_AWS_ACCESS_KEY_ID, RW_AWS_SECRET_ACCESS_KEY, awsEndpointOverride);
final SecureRandom secureRandom = new SecureRandom();

for (int i = 0; i < 4; i++) {
Expand All @@ -88,7 +97,7 @@ void setupAwsResources() {
}
}

@ParameterizedTest
@ParameterizedTest(name = "{index} - Using config file: {0}")
@ValueSource(booleans = {true, false})
void secretsAreLoadedFromAWSSecretsManagerAndReportedByPublicApi(final boolean useConfigFile) {
final AwsSecretsManagerParameters awsSecretsManagerParameters =
Expand All @@ -100,6 +109,7 @@ void secretsAreLoadedFromAWSSecretsManagerAndReportedByPublicApi(final boolean u
.withPrefixesFilter(List.of(awsSecretsManagerUtil.getSecretsManagerPrefix()))
.withTagNamesFilter(List.of("TagName0", "TagName1"))
.withTagValuesFilter(List.of("TagValue0", "TagValue1", "TagValue2"))
.withEndpointOverride(awsEndpointOverride)
.build();

final SignerConfigurationBuilder configBuilder =
Expand All @@ -110,6 +120,13 @@ void secretsAreLoadedFromAWSSecretsManagerAndReportedByPublicApi(final boolean u

startSigner(configBuilder.build());

signer
.healthcheck()
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("status", equalTo("UP"));

signer
.callApiPublicKeys(KeyType.BLS)
.then()
Expand All @@ -124,7 +141,7 @@ void secretsAreLoadedFromAWSSecretsManagerAndReportedByPublicApi(final boolean u
hasSize(2));
}

@ParameterizedTest
@ParameterizedTest(name = "{index} - Using config file: {0}")
@ValueSource(booleans = {true, false})
void secretsAreLoadedFromAWSSecretsManagerWithEnvironmentAuthModeAndReportedByPublicApi(
final boolean useConfigFile) {
Expand All @@ -134,6 +151,7 @@ void secretsAreLoadedFromAWSSecretsManagerWithEnvironmentAuthModeAndReportedByPu
.withPrefixesFilter(List.of(awsSecretsManagerUtil.getSecretsManagerPrefix()))
.withTagNamesFilter(List.of("TagName2", "TagName3"))
.withTagValuesFilter(List.of("TagValue0", "TagValue2", "TagValue3"))
.withEndpointOverride(awsEndpointOverride)
.build();

final SignerConfigurationBuilder configBuilder =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import tech.pegasys.web3signer.signing.config.AwsSecretsManagerParametersBuilder;
import tech.pegasys.web3signer.tests.AcceptanceTestBase;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -70,6 +71,12 @@ public class AwsSecretsManagerMultiValueAcceptanceTest extends AcceptanceTestBas
private static final String RO_AWS_SECRET_ACCESS_KEY = System.getenv("AWS_SECRET_ACCESS_KEY");
private static final String AWS_REGION =
Optional.ofNullable(System.getenv("AWS_REGION")).orElse("us-east-2");

// can be pointed to localstack
private final Optional<URI> awsEndpointOverride =
System.getenv("AWS_ENDPOINT_OVERRIDE") != null
? Optional.of(URI.create(System.getenv("AWS_ENDPOINT_OVERRIDE")))
: Optional.empty();
private AwsSecretsManagerUtil awsSecretsManagerUtil;
private final List<BLSKeyPair> blsKeyPairList = new ArrayList<>(400);

Expand All @@ -80,7 +87,8 @@ void setupAwsResources() {
}

awsSecretsManagerUtil =
new AwsSecretsManagerUtil(AWS_REGION, RW_AWS_ACCESS_KEY_ID, RW_AWS_SECRET_ACCESS_KEY);
new AwsSecretsManagerUtil(
AWS_REGION, RW_AWS_ACCESS_KEY_ID, RW_AWS_SECRET_ACCESS_KEY, awsEndpointOverride);

for (int i = 0; i < 4; i++) {
String multilinePrivKeys =
Expand All @@ -103,6 +111,7 @@ void secretsAreLoadedFromAWSSecretsManagerAndReportedByPublicApi(final boolean u
.withSecretAccessKey(RO_AWS_SECRET_ACCESS_KEY)
.withPrefixesFilter(List.of(awsSecretsManagerUtil.getSecretsManagerPrefix()))
.withTagNamesFilter(List.of("multivalue"))
.withEndpointOverride(awsEndpointOverride)
.build();

final SignerConfigurationBuilder configBuilder =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import tech.pegasys.web3signer.signing.config.AwsSecretsManagerParametersBuilder;
import tech.pegasys.web3signer.tests.AcceptanceTestBase;

import java.net.URI;
import java.security.SecureRandom;
import java.time.Duration;
import java.util.Collections;
Expand Down Expand Up @@ -79,6 +80,12 @@ public class AwsSecretsManagerPerformanceAcceptanceTest extends AcceptanceTestBa
private static final String RO_AWS_SECRET_ACCESS_KEY = System.getenv("AWS_SECRET_ACCESS_KEY");
private static final String AWS_REGION =
Optional.ofNullable(System.getenv("AWS_REGION")).orElse("us-east-2");

// can be pointed to localstack
private final Optional<URI> awsEndpointOverride =
System.getenv("AWS_ENDPOINT_OVERRIDE") != null
? Optional.of(URI.create(System.getenv("AWS_ENDPOINT_OVERRIDE")))
: Optional.empty();
private static final Integer NUMBER_OF_KEYS =
Integer.parseInt(Optional.ofNullable(System.getenv("AWS_PERF_AT_KEYS_NUM")).orElse("1000"));
private static final Duration STARTUP_TIMEOUT = Duration.ofMinutes(10);
Expand All @@ -90,7 +97,8 @@ void setupAwsResources() {
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
awsSecretsManagerUtil =
new AwsSecretsManagerUtil(AWS_REGION, RW_AWS_ACCESS_KEY_ID, RW_AWS_SECRET_ACCESS_KEY);
new AwsSecretsManagerUtil(
AWS_REGION, RW_AWS_ACCESS_KEY_ID, RW_AWS_SECRET_ACCESS_KEY, awsEndpointOverride);
final SecureRandom secureRandom = new SecureRandom();
LOG.info("Creating {} AWS keys in Secrets Manager in {}", NUMBER_OF_KEYS, AWS_REGION);
blsKeyPairs =
Expand Down Expand Up @@ -119,6 +127,7 @@ void largeNumberOfKeysAreLoadedSuccessfully() {
.withAccessKeyId(RO_AWS_ACCESS_KEY_ID)
.withSecretAccessKey(RO_AWS_SECRET_ACCESS_KEY)
.withPrefixesFilter(List.of(awsSecretsManagerUtil.getSecretsManagerPrefix()))
.withEndpointOverride(awsEndpointOverride)
.build();

final SignerConfigurationBuilder configBuilder =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package tech.pegasys.web3signer.tests.bulkloading;

import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;

import tech.pegasys.web3signer.dsl.signer.SignerConfigurationBuilder;
Expand Down Expand Up @@ -58,6 +59,13 @@ void ensureSecretsInKeyVaultAreLoadedAndReportedViaPublicKeysApi() {

final Response response = signer.callApiPublicKeys(KeyType.BLS);
response.then().statusCode(200).contentType(ContentType.JSON).body("", contains(EXPECTED_KEY));

signer
.healthcheck()
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("status", equalTo("UP"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, be good to have a test showing that checks have the appropriate status and error count values

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added it in AWS Secrets Manager AT.

}

@Test
Expand All @@ -72,6 +80,13 @@ void invalidVaultParametersFailsToLoadKeys() {

final Response response = signer.callApiPublicKeys(KeyType.BLS);
response.then().statusCode(200).contentType(ContentType.JSON).body("", hasSize(0));

signer
.healthcheck()
.then()
.statusCode(503)
.contentType(ContentType.JSON)
.body("status", equalTo("DOWN"));
}
jframe marked this conversation as resolved.
Show resolved Hide resolved

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import tech.pegasys.web3signer.AwsSecretsManagerUtil;

import java.net.URI;
import java.util.Collections;
import java.util.Optional;

Expand Down Expand Up @@ -59,6 +60,12 @@ public class AwsKeyIdentifiersAcceptanceTest extends KeyIdentifiersAcceptanceTes
private static final String AWS_REGION =
Optional.ofNullable(System.getenv("AWS_REGION")).orElse("us-east-2");

// can be pointed to localstack
private final Optional<URI> awsEndpointOverride =
System.getenv("AWS_ENDPOINT_OVERRIDE") != null
? Optional.of(URI.create(System.getenv("AWS_ENDPOINT_OVERRIDE")))
: Optional.empty();

private final String privateKey = privateKeys(BLS)[0]; // secret value
private final String publicKey = BLS_PUBLIC_KEY_1;

Expand All @@ -67,7 +74,8 @@ public class AwsKeyIdentifiersAcceptanceTest extends KeyIdentifiersAcceptanceTes
@BeforeAll
void setup() {
awsSecretsManagerUtil =
new AwsSecretsManagerUtil(AWS_REGION, RW_AWS_ACCESS_KEY_ID, RW_AWS_SECRET_ACCESS_KEY);
new AwsSecretsManagerUtil(
AWS_REGION, RW_AWS_ACCESS_KEY_ID, RW_AWS_SECRET_ACCESS_KEY, awsEndpointOverride);
awsSecretsManagerUtil.createSecret(publicKey, privateKey, Collections.emptyMap());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import tech.pegasys.web3signer.dsl.utils.MetadataFileHelpers;
import tech.pegasys.web3signer.signing.KeyType;

import java.net.URI;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Optional;
Expand Down Expand Up @@ -178,10 +179,16 @@ public void ableToSignUsingAws() throws JsonProcessingException {
final String roAwsAccessKeyId = System.getenv("AWS_ACCESS_KEY_ID");
final String roAwsSecretAccessKey = System.getenv("AWS_SECRET_ACCESS_KEY");
final String region = Optional.ofNullable(System.getenv("AWS_REGION")).orElse("us-east-2");
// can be pointed to localstack
final Optional<URI> awsEndpointOverride =
System.getenv("AWS_ENDPOINT_OVERRIDE") != null
? Optional.of(URI.create(System.getenv("AWS_ENDPOINT_OVERRIDE")))
: Optional.empty();
final String publicKey = KEY_PAIR.getPublicKey().toString();

final AwsSecretsManagerUtil awsSecretsManagerUtil =
new AwsSecretsManagerUtil(region, rwAwsAccessKeyId, rwAwsSecretAccessKey);
new AwsSecretsManagerUtil(
region, rwAwsAccessKeyId, rwAwsSecretAccessKey, awsEndpointOverride);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this appropriate test or not but would be good to have a test case for config-files-loading check as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added healthcheck AT related to config-files-loading.


awsSecretsManagerUtil.createSecret(publicKey, PRIVATE_KEY, Collections.emptyMap());
final String fullyPrefixKeyName = awsSecretsManagerUtil.getSecretsManagerPrefix() + publicKey;
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ allprojects {
targetCompatibility = 11

repositories {
mavenLocal() //TODO: Remove me
usmansaleem marked this conversation as resolved.
Show resolved Hide resolved
mavenCentral()
maven { url "https://artifacts.consensys.net/public/maven/maven/" }
maven { url "https://artifacts.consensys.net/public/teku/maven/" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
import tech.pegasys.web3signer.signing.config.AwsAuthenticationMode;
import tech.pegasys.web3signer.signing.config.AwsSecretsManagerParameters;

import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import picocli.CommandLine;
import picocli.CommandLine.Option;
Expand All @@ -29,6 +31,7 @@ public class PicoCliAwsSecretsManagerParameters implements AwsSecretsManagerPara
public static final String AWS_SECRETS_SECRET_ACCESS_KEY_OPTION =
"--aws-secrets-secret-access-key";
public static final String AWS_SECRETS_REGION_OPTION = "--aws-secrets-region";
public static final String AWS_ENDPOINT_OVERRIDE_OPTION = "--aws-endpoint-override";
public static final String AWS_SECRETS_PREFIXES_FILTER_OPTION = "--aws-secrets-prefixes-filter";
public static final String AWS_SECRETS_TAG_NAMES_FILTER_OPTION = "--aws-secrets-tag-names-filter";
public static final String AWS_SECRETS_TAG_VALUES_FILTER_OPTION =
Expand Down Expand Up @@ -72,6 +75,12 @@ public class PicoCliAwsSecretsManagerParameters implements AwsSecretsManagerPara
paramLabel = "<Region>")
private String region;

@Option(
names = {AWS_ENDPOINT_OVERRIDE_OPTION},
description = "Override AWS endpoint.",
paramLabel = "<URI>")
private Optional<URI> endpointOverride;

@Option(
names = AWS_SECRETS_PREFIXES_FILTER_OPTION,
description =
Expand Down Expand Up @@ -147,4 +156,9 @@ public Collection<String> getTagNamesFilter() {
public Collection<String> getTagValuesFilter() {
return tagValuesFilter;
}

@Override
public Optional<URI> getEndpointOverride() {
return endpointOverride;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ protected ArtifactSignerProvider createArtifactSignerProvider(
"yaml",
new YamlSignerParser(
List.of(ethSecpArtifactSignerFactory),
YamlMapperFactory.createYamlMapper(config.getKeyStoreConfigFileMaxSize())));
YamlMapperFactory.createYamlMapper(config.getKeyStoreConfigFileMaxSize())))
.getValues();
}
});
}
Expand Down
Loading