Skip to content

Conversation

danielthegray
Copy link
Contributor

@danielthegray danielthegray commented Aug 7, 2024

Impact

  • Bug fix (non-breaking change which fixes expected existing functionality)
  • Enhancement/New feature (adds functionality without impacting existing logic)
  • Breaking change (fix or feature that would cause existing functionality to change)

Description

SecureRandom is a robust RNG for use in security-sensitive scenarios (like generating cryptographic/private keys). For something like a random Scope ID, it is overkill, as it's slower, and becomes a potentially blocking call if the machine hasn't been on for long or have enough entropy.

I've looked into the original change (in commit 3daa688) and it seems to have been done to improve the performance of the Scope ID generation. While it clearly did improve things, it's much better to just use a normal ThreadLocalRandom instance, that will not experience contention issues even under high traffic, and will not have the problem with depending on system entropy.

The original change (in commit 3daa688) already did this change implicitly, since RandomStringUtils up to version 3.14 was using ThreadLocalRandom. So from Liquibase's perspective, this maintains the improved performance profile without making it subject to the whims of Apache Commons Lang3.

Fixes #6178. I built a local liquibase-core JAR and linked into my CLI tool, and the changeset deployment no longer hangs.

Things to be aware of

This makes the Scope ID generation not use a SecureRandom instance anymore, but it should really not be a problem as it should not require cryptographic-level randomness.
This is just setting your Scope ID generation to use ThreadLocalRandom again, more explicitly, and in a way that cannot be arbitrarily changed by myopic library maintainers :)

Things to worry about

I think that the performance should actually be much better than the previous implemented fix (using Apache Commons), but I have not tested your use-case. I would recommend that you test it and see what the actual performance impact is.

Actually, you did the change initially, to move away from SecureRandom to ThreadLocalRandom, and the Apache Commons Lang3 team just changed that out from under you in v3.15, not just back to SecureRandom but all the way to SecureRandom.getInstanceStrong() which will make this block/take forever. So I see nothing more to worry about :)

SecureRandom is a robust RNG for use in security-sensitive scenarios
(like generating cryptographic/private keys). For something like a
random Scope ID, it is overkill, as it's slower, and becomes a
potentially blocking call if the machine hasn't been on for long or have
enough entropy.

It's much better to just use a normal ThreadLocalRandom instance, that
will not experience contention issues even under high traffic.
Copy link
Collaborator

@filipelautert filipelautert left a comment

Choose a reason for hiding this comment

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

Thanks for the PR @danielthegray !

@filipelautert filipelautert changed the base branch from master to release August 14, 2024 19:45
@danielthegray
Copy link
Contributor Author

I think you'll also want to check your usage of RandomStringUtils in liquibase-integration-tests/src/test/groovy/liquibase/diffchangelog/DiffChangelogMssqlIntegrationTest.groovy, as under the new implementation this test could run slower or block, although with just 2 invocations, maybe it won't be too big of a deal, but I would suggest that you just stop using RandomStringUtils.

I have definitely banned this class from my codebase as this irresponsible behavior make this class a foot-gun for future colleagues.

Copy link
Contributor

@tati-qalified tati-qalified left a comment

Choose a reason for hiding this comment

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

The prior version of this method returned strings that contained both upper and lowercase letters, while the new version uses only uppercase.
@filipelautert I think it would be best to add all lowercase letters to final String AB = "<...>". Thoughts?

@filipelautert
Copy link
Collaborator

The prior version of this method returned strings that contained both upper and lowercase letters, while the new version uses only uppercase. @filipelautert I think it would be best to add all lowercase letters to final String AB = "<...>". Thoughts?

The original code before using RandomStringUtils only used uppercase letters too, so that's not an issue ;)

@filipelautert filipelautert modified the milestones: 1NEXT, 4.29.2 Aug 19, 2024
@filipelautert filipelautert merged commit 867f787 into liquibase:release Aug 19, 2024
24 of 27 checks passed
@danielthegray danielthegray deleted the improve_scope_id_rng branch August 22, 2024 14:45
tesshucom added a commit to tesshucom/jpsonic that referenced this pull request Sep 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Liquibase hangs when trying to apply changesets on a newly created machine
4 participants