-
Notifications
You must be signed in to change notification settings - Fork 156
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
[SECURITY-2053] Prevent plain text credentials of Basic/Digest authentication #105
[SECURITY-2053] Prevent plain text credentials of Basic/Digest authentication #105
Conversation
Related: jenkins-infra/helpdesk#3075 |
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 would expect this approach to result in warnings about unloadable data.
Might work better from an admin POV to remove all UI and make the field of HttpRequestGlobalConfig
transient
.
|
||
private final String keyName; | ||
private final String userName; | ||
private final String 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.
FTR the only required change was to change this field's type to hudson.util.Secret
(ideally also constructor parameter and getter return value), and adapt related code as needed.
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.
Thanks for the review!
The class is marked as deprecated for years and the UI indicates that too. I wouldn't consider this worth the effort of an API change / migration. It's a good chance to remove it for good now. There shouldn't be any use case left … hopefully.
I don't have a strong opinion on this though. So if either making fields transient or migration to Secret are more suitable solution to fix this I can update the PR.
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.
Per the developer documentation:
Removing a field requires that you leave the field with the
transient
keyword. When Jenkins reads the old XML, XStream will set the value for this field, but it will no longer be written back to XML when data is saved.
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.
Is there any workflow on how to remove a class?
If I understand this correctly transient (all fields?) + UI removal is the preferred solution? PR update is on the way.
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.
Is there any workflow on how to remove a class?
Good question, it's not a case I had to handle before -- usually old types are kept around to do migration of old configuration or data to the new types, and then transient
+ readResolve
do the job.
I'd probably keep the class, and make the field holding it transient
. Then the idea would be to make the class an empty shell. I'd try implementing #readObject(ObjectInputStream)
or an X-Stream Converter
(as a nested class called ConverterImpl
) to bypass any warnings from default behaviors, and basically do as little as possible.
(You could customize the deserialization of the class holding the field, but that doesn't seem like a great idea for longer-term maintainability.)
Regarding the comment that started this thread, it was only to point out what a minimal fix would have looked like. We're generally not asking maintainers to rip out entire features, and I did not want this PR to give this impression.
e24d3b8
to
6a41582
Compare
PR updated:
|
FTR the field I would suggest making transient is e24d3b8#diff-e6782195225aa77d34dd0c71b85cabe588c8a7a632b36fb73198a981d63e3e7cL31. |
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.
Change is incomplete:
help-userName.html
andhelp-password.html
are not shown in the UI but are still present in the repository- We still serialize a
<basicDigestAuthentications>
when saving anHttpRequestGlobalConfig
object; we don't want to serialize anything related to basic digest authentication anymore. - Once the above feedback is addressed by marking the
basicDigestAuthentications
field as transient, its getters and setters should be deprecated, as calling them will update an in-memory object that will not be persisted - Once the above feedback is addressed usages of the above need to be audited and deleted; we don't want to be invoking a method that will write an object to memory that will then be discarded when the object is serialized
- Probably also want to clear any existing deprecated data in memory after reading it from the old version via a
readResolve
method as described in the developer documentation
Ah, I see! This would also get rid of the – now empty – list element. 👍 |
Thanks @basil, I'm going to work on your suggestions. --
|
and it's deprecate getter / setter.
Public:The setter is used in tests only, getter in tests and filling of the authentication items list box (HttpRequest.DescriptorImpl). Internal:Key validation (must be unique) and mapping of key to Authenticator. |
1e5984b
to
29ff54c
Compare
From another perspective, perhaps unloadable data might be a good UX? Because that way administrators could choose when to delete the plaintext usernames and passwords from disk, whereas without the new approach we would delete the plaintext usernames and passwords from disk when the job is next saved. That might violate the principle of least surprise by deleting data, and perhaps some users would be upset to lose their usernames and passwords without explicitly asking to do so. What do you think @daniel-beck @offa? |
Does unloadable data affect the basic digest elements (= good) or delete the complete data / XML file (= bad)? In the former case it sounds like a good approach to me 👍. |
Unloadable data doesn't cause any problems for users, but it results in an administrative warning in the Manage Jenkins UI (which has an Old Data page). The administrator than has to press a button to clear the old data. @daniel-beck seems to think that's a bug, but I think it might be considered a feature because it forces the administrator to think about whether they want to erase the old usernames and passwords before they are lost. |
It's usually indicative of a bug in code that was changed incompatibly. Your argument is reasonable though. (IIRC we've never opened up the more user friendly "old data" API to plugins, so it'd be cumbersome to offer a better UX, would need to be a custom admin monitor, and that doesn't seem worth it.) Note however that saving the global config form will drop unloadable data, so it's not really straightforward to retain the data on disk. |
Now, how continue here? |
I did some quick testing with a freestyle job. The job continues to list and use the credentials after switching to this PR version and getting them removed from global config. After a Jenkins restart it jumps to - none - in the jobs UI and build fail with an exception ( |
Both done, assuming the next release version is 1.16. |
Seems tolerable. Depending on how much time you want to invest here, this can probably be done nicer, e.g. telling admins which jobs are losing their configured authentication. But that's potentially a lot more work. Since I forgot to mention it before and I don't know whether you are aware of this: Please note that the Jenkins security team will not release a new version of this plugin. We're happy to help resolve the issue of course, and we'll update the security warning to mark future releases as fixed, but releasing this plugin must be done by current or future maintainers. |
Not too much honestly (it's a long time deprecated feature, which isn't used extensively hopefully).
I know, but at least I can prepare a fix which is confirmed to solve the issue. Btw. thanks a lot at this point @daniel-beck @basil for helping me here! |
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.
Previous review feedback not addressed: no readResolve
, deprecated usages still present, etc.
* @deprecated removed without replacement | ||
*/ | ||
@Deprecated | ||
private transient List<BasicDigestAuthentication> basicDigestAuthentications = new ArrayList<>(); |
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.
Usage of deprecated field still present in HttpRequestGlobalConfig#getAuthentications
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 have removed the usage from getAuthentications()
. The other two usages are getter and setter.
What is the best scenario for those? If getter / setter are deprecated but still available I'd suggest keeping the related test cases too (it's still some kind of public API), or remove getter, setter, field (?) and related tests altogether.
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.
Please remove all callers of deprecated methods but retain the methods for binary compatibility
src/main/java/jenkins/plugins/http_request/HttpRequestGlobalConfig.java
Outdated
Show resolved
Hide resolved
@@ -109,7 +109,7 @@ public void setFormAuthentications( | |||
} | |||
|
|||
public List<Authenticator> getAuthentications() { | |||
return new ArrayList<>(formAuthentications); | |||
return new ArrayList<>(formAuthentications); |
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 project is configured to use tabs (Intelij + Eclipse settings). :-(
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.
Thanks for the PR!
Removes Basic / Digest authentication in order to fix SECURITY-2053.
It has been deprecated and marked for removal in 1.8.19+ anyway (we are 1.15 now).
Here are my steps used to reproduce the issue and verify my fix:
Reproduce
Verify the fix
Reviewer
@jenkinsci/http-request-plugin-developers and security team (@Wadeck @daniel-beck)