Skip to content

Commit

Permalink
Merge pull request #156 from felixkrull-neuland/verify-checksum
Browse files Browse the repository at this point in the history
Disallow changes to previously successfully applied scripts
  • Loading branch information
maaaNu authored Oct 11, 2022
2 parents dbe4c24 + b0f679f commit 94d7bd5
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 29 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ Elasticsearch-Evolution can be configured to your needs:
- **placeholderSuffix** (default=}): Suffix of placeholders in migration scripts.
- **historyIndex** (default=es_evolution): Name of the history index that will be used by Elasticsearch-Evolution. In this index Elasticsearch-Evolution will persist his internal state and tracks which migration script has already been executed.
- **historyMaxQuerySize** (default=1000): The maximum query size while validating already executed scripts. This query size have to be higher than the total count of your migration scripts.
- **validateOnMigrate** (default=true): Whether to fail when a previously applied migration script has been modified after it was applied.

### 5.1 Spring Boot

Expand Down Expand Up @@ -288,12 +289,16 @@ ElasticsearchEvolution.configure()

### v0.4.1-SNAPSHOT


- Previously applied migration scripts are now checked for modifications and rejected if they've been modified after they were applied. The old behaviour can be restored by setting the new configuration parameter `validateOnMigrate` to false (default: true) ([#155](https://github.com/senacor/elasticsearch-evolution/isse/155))

- version updates (spring-boot 2.7.4)
- added java 19 compatibility tests
- added spring boot 2.7 compatibility tests
- added Elasticsearch 8.4, 8.3, and 8,2 compatibility tests
- added Elasticsearch 8.4, 8.3, and 8,2 compatibility test
- added Opensearch 2.3, 2.2, 2.1 and 2.0 compatibility tests


### v0.4.0

- **breaking change**: drop `org.elasticsearch.client.RestHighLevelClient` and replace with `org.elasticsearch.client.RestClient` (LowLevelClient). This will drop the big transitive dependency `org.elasticsearch:elasticsearch` and opens compatibility to Elasticsearch 8 and OpenSearch.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ protected MigrationService createMigrationService() {
10_000,
getRestClient(),
ContentType.parse(getConfig().getDefaultContentType()),
getConfig().getEncoding());
getConfig().getEncoding(),
getConfig().getValidateOnMigrate());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ public class ElasticsearchEvolutionConfig {
*/
private int historyMaxQuerySize = 1_000;

/**
* Whether to fail when a previously applied migration script has been modified after it was applied.
*/
private boolean validateOnMigrate = true;

/**
* Loads this configuration into a new ElasticsearchEvolution instance.
*
Expand Down Expand Up @@ -236,6 +241,15 @@ public ElasticsearchEvolutionConfig setHistoryMaxQuerySize(int historyMaxQuerySi
return this;
}

public boolean getValidateOnMigrate() {
return validateOnMigrate;
}

public ElasticsearchEvolutionConfig setValidateOnMigrate(boolean validateOnMigrate) {
this.validateOnMigrate = validateOnMigrate;
return this;
}

@Override
public String toString() {
return "ElasticsearchEvolutionConfig{" +
Expand All @@ -251,6 +265,7 @@ public String toString() {
", placeholderReplacement=" + placeholderReplacement +
", historyIndex='" + historyIndex + '\'' +
", historyMaxQuerySize=" + historyMaxQuerySize +
", validateOnMigrate=" + validateOnMigrate +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,20 @@ public class MigrationServiceImpl implements MigrationService {
private final RestClient restClient;
private final ContentType defaultContentType;
private final Charset encoding;
private final boolean validateOnMigrate;

public MigrationServiceImpl(HistoryRepository historyRepository,
int waitUntilUnlockedMinTimeInMillis,
int waitUntilUnlockedMaxTimeInMillis,
RestClient restClient,
ContentType defaultContentType,
Charset encoding) {
Charset encoding,
boolean validateOnMigrate) {
this.historyRepository = requireNonNull(historyRepository, "historyRepository must not be null");
this.restClient = requireNonNull(restClient, "restClient must not be null");
this.defaultContentType = requireNonNull(defaultContentType);
this.encoding = requireNonNull(encoding);
this.validateOnMigrate = validateOnMigrate;
this.waitUntilUnlockedMinTimeInMillis = requireCondition(waitUntilUnlockedMinTimeInMillis,
min -> min >= 0 && min <= waitUntilUnlockedMaxTimeInMillis,
"waitUntilUnlockedMinTimeInMillis (%s) must not be negative and must not be greater than waitUntilUnlockedMaxTimeInMillis (%s)",
Expand Down Expand Up @@ -185,9 +188,20 @@ List<ParsedMigrationScript> getPendingScriptsToBeExecuted(Collection<ParsedMigra
ParsedMigrationScript parsedMigrationScript = orderedScripts.get(i);
if (!protocol.getVersion().equals(parsedMigrationScript.getFileNameInfo().getVersion())) {
throw new MigrationException(String.format(
"The logged execution in the Elasticsearch-Evolution history index at position %s is version %s and in the same position in the given migration scripts is version %s! Out of order execution is not supported. Or maybe you have added new migration scripts in between or have to cleanup the Elasticsearch-Evolution history index manually",
"The logged execution in the Elasticsearch-Evolution history index at position %s " +
"is version %s and in the same position in the given migration scripts is version %s! " +
"Out of order execution is not supported. Or maybe you have added new migration scripts " +
"in between or have to cleanup the Elasticsearch-Evolution history index manually",
i, protocol.getVersion(), parsedMigrationScript.getFileNameInfo().getVersion()));
}
// failed scripts can be edited and retried, but successfully executed scripts may not be modified afterwards
if (validateOnMigrate && protocol.isSuccess() && protocol.getChecksum() != parsedMigrationScript.getChecksum()) {
throw new MigrationException(String.format(
"The logged execution for the migration script at position %s (%s) " +
"has a different checksum from the given migration script! " +
"Modifying already-executed scripts is not supported.",
i, protocol.getScriptName()));
}

if (protocol.isSuccess()) {
res.remove(parsedMigrationScript);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void OK_indexDocumentIsWrittenToElasticsearch(String versionInfo, EsUtils esUtil

MigrationServiceImpl underTest = new MigrationServiceImpl(historyRepositoryMock,
0, 0, restHighLevelClient.getLowLevelClient(),
defaultContentType, encoding);
defaultContentType, encoding, true);

MigrationScriptProtocol res = underTest.executeScript(script).getProtocol();

Expand Down
Loading

0 comments on commit 94d7bd5

Please sign in to comment.