-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
solved issue "certutil: large passwords not set" #30944 #36689
Conversation
Fixed the issue about passwords longer than 50 not working on older versions of OpenSSL. From now on, users get an alert when they try to put a password with length above 50 and they have an OpenSSL version lower than 1.1.0, giving then the opportunity ti prompt one password again.
.../plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertificateTool.java
Outdated
Show resolved
Hide resolved
Pinging @elastic/es-security |
(warning for all versions)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @MiguelFerreira1998 and @bedgarone
Thanks for your contribution on this issue. I've left some suggestions.
}); | ||
} | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like all of this section is whitespace changes (extra blank lines, additional indentation) that aren't needed.
return body.apply(promptedValue); | ||
} finally { | ||
Arrays.fill(promptedValue, (char) 0); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The withPassword
method is called every time we need a password, even if it's being used to read a certificate file.
In that case we don't want to print this warning, because that would cause additional output (and an additional prompt) for simple things like reading a CA file that has a long password.
We need to only perform this check/warning if the password is being applied to a new file.
I'm OK if we want get rid of the promptYesNo
and just print out a warning, but we only want to do either of them when we know the password is being used to write a file.
} | ||
else{ | ||
long_size = false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The formatting of thise code (spaces around brackets etc) is different to the way the rest of this source code is formatted. By the time we get to the end of this review process, we'll want to have it formatted in the same style as the surrounding code.
Thanks @tvernum for all the support. I will be committing what i think its a fix. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some more feedback.
Arrays.fill(promptedValue, (char) 0); | ||
while(long_size){ | ||
if(promptedValue.length > MAX_SIZE_PW_BUFFER_OLDER_SSL){ | ||
if(terminal.promptYesNo("Your password exceeds a length of 50 characters. Versions of OpenSSL older than 1.1.0 will not be able to use this certificate. Do you want to continue?", true)){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having through about this a bit more, I think the prompt is going to be annoying rather than helpful.
I think we'd be better off just printing out a warning message, and continuing on.
Sorry for messing things around like this, but sometimes things become clearer during the review cycle.
@@ -381,7 +381,7 @@ CAInfo generateCA(Terminal terminal, OptionSet options) throws Exception { | |||
return new CAInfo(caCert, keyPair.getPrivate(), true, password); | |||
} | |||
if (options.has(caPasswordSpec)) { | |||
return withPassword("CA Private key", null, terminal, p -> new CAInfo(caCert, keyPair.getPrivate(), true, p.clone())); | |||
return withPassword("CA Private key",false, null, terminal, p -> new CAInfo(caCert, keyPair.getPrivate(), true, p.clone())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one should be true
.
We want to check the password length any time we're generating a new private key.
@@ -527,7 +527,8 @@ static void writeCAInfo(ZipOutputStream outputStream, CAInfo info, Terminal term | |||
final String dirName = createCaDirectory(outputStream); | |||
final String fileName = dirName + "ca.p12"; | |||
outputStream.putNextEntry(new ZipEntry(fileName)); | |||
withPassword("Generated CA", info.password, terminal, caPassword -> { | |||
|
|||
withPassword("Generated CA", false, info.password, terminal, caPassword -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to be true
as well.
@@ -794,7 +797,8 @@ void generateAndWriteSignedCertificates(Path output, boolean writeZipFile, Optio | |||
final String keyFileName = entryBase + ".key"; | |||
outputStream.putNextEntry(new ZipEntry(keyFileName)); | |||
if (usePassword) { | |||
withPassword(keyFileName, outputPassword, terminal, password -> { | |||
|
|||
withPassword(keyFileName, false, outputPassword, terminal, password -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this one needs to be true
@@ -923,15 +927,29 @@ private static PEMEncryptor getEncrypter(char[] password) { | |||
return new JcePEMEncryptorBuilder("DES-EDE3-CBC").setProvider(BC_PROV).build(password); | |||
} | |||
|
|||
private static <T, E extends Exception> T withPassword(String description, char[] password, Terminal terminal, | |||
private static <T, E extends Exception> T withPassword(String description, boolean long_size, char[] password, Terminal terminal, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than long_size
, it would be better to name this parameter something like forNewKey
so it describes the logical purpose of the parameter.
@elasticmachine test this please |
@ywangd Can you do a quick review of my additions to this PR? |
String wrongPassword = randomAlphaOfLengthBetween(8, 20); | ||
terminal.addSecretInput(wrongPassword); | ||
terminal.addSecretInput("__" + wrongPassword); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't really related to this PR, but I noticed it was a gap in testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. But the PR description seems to be off:
I check the current version of the user and i prompt a warn message if they input a password longer than 50 and they are using OpenSLL under version 1.1.0
Only the password length is checked and warning is issued regardless. There is no check for OpenSSL version and in fact it is not viable to do so. If my understand is correct, I suggest we update the description before merge.
"Warning: Your password exceeds " | ||
+ MAX_PASSWORD_OLD_OPENSSL | ||
+ " characters. Versions of OpenSSL older than " | ||
+ OLD_OPENSSL_VERSION | ||
+ " may not be able to read this file." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Warning: Your password exceeds " | |
+ MAX_PASSWORD_OLD_OPENSSL | |
+ " characters. Versions of OpenSSL older than " | |
+ OLD_OPENSSL_VERSION | |
+ " may not be able to read this file." | |
"Warning: Your password exceeds [" | |
+ MAX_PASSWORD_OLD_OPENSSL | |
+ "] characters. Versions of OpenSSL older than [" | |
+ OLD_OPENSSL_VERSION | |
+ "] may not be able to read this file." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? They're constants, so we don't need the braces in order to see where the variable part is substituted in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought the braces are for emphasis. But if they are just for variables, then you are right that we don't need them here.
.../plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertificateTool.java
Outdated
Show resolved
Hide resolved
@@ -924,16 +929,43 @@ static PEMEncryptor getEncrypter(char[] password) { | |||
return new JcePEMEncryptorBuilder("AES-128-CBC").setProvider(BC_PROV).build(password); | |||
} | |||
|
|||
private static <T, E extends Exception> T withPassword(String description, char[] password, Terminal terminal, | |||
static boolean checkPasswordLengthForOpenSSLCompatibility(char[] password, Terminal terminal, boolean confirm) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
This method and parameter names confused me for a bit. They made me think that the behaviour when confirm
is false
should be return false
if password is too long. But instead the default behaviour is return true
unless user says otherwise and confirm
is to let user have that say. Maybe:
static boolean checkPasswordLengthForOpenSSLCompatibility(char[] password, Terminal terminal, boolean confirm) { | |
static boolean maybeWarnAndConfirmPasswordLengthForOpenSSLCompatibility(char[] password, Terminal terminal, boolean confirmRequired) { |
It is quite verbose, but it feels more accurate to me. I am also happy if you can come up with something better.
...in/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertificateToolTests.java
Show resolved
Hide resolved
...rity/cli/src/test/java/org/elasticsearch/xpack/security/cli/HttpCertificateCommandTests.java
Outdated
Show resolved
Hide resolved
@elasticmachine test this please 🙏 |
Resolves #30944 |
Older versions of OpenSSL (prior to 1.1.0) had a fixed 50 char buffer for password input. This means that keys (etc) encrypted with a password > 50 chars cannot be used by old versions of OpenSSL. This change adds warnings/prompts when creating encrypted files with passwords longer than 50 characters in elasticsearch-certutil. Backport of: elastic#36689 Co-authored-by: MiguelFerreira1998 <[email protected]>
Older versions of OpenSSL (prior to 1.1.0) had a fixed 50 char buffer for password input. This means that keys (etc) encrypted with a password > 50 chars cannot be used by old versions of OpenSSL. This change adds warnings/prompts when creating encrypted files with passwords longer than 50 characters in elasticsearch-certutil. Backport of: #36689 Co-authored-by: MiguelFerreira1998 <[email protected]> Co-authored-by: MiguelFerreira1998 <[email protected]>
Older versions of OpenSSL couldn't support passwords for a new Certificate Authority larger than 50 characters. I check the current version of the user and i prompt a warn message if they input a password longer than 50 and they are using OpenSLL under version 1.1.0