-
Notifications
You must be signed in to change notification settings - Fork 164
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
Implemented writeYaml step #23
Conversation
pom.xml
Outdated
@@ -28,7 +28,7 @@ | |||
<parent> | |||
<groupId>org.jenkins-ci.plugins</groupId> | |||
<artifactId>plugin</artifactId> | |||
<version>1.609.1</version> | |||
<version>2.19</version> |
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 do you need this?
I don't see any reason for it. As I've said in previous PRs; When we bump anything here I want to see a more rigorous cleanup for example moving to more recent workflow.version and cleaning up all @Inject
etc. And that should go in a separate 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.
The real reason was to bump surefire plugin up to 2.19.1 so testing could be done with -Dtest=method1#method2. Will revert the change
|
||
@Override | ||
public Step newInstance(Map<String, Object> arguments) throws Exception { | ||
WriteYamlStep step = new WriteYamlStep(); |
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 doubt this is needed for this step, skip it and just put file
and data
as required params in the @DataBoundConstructor
.
The special handling here that you've seen in other steps are because they have an either or relation that can't be expressed in a better way.
|
||
@Override | ||
protected Void run () throws Exception { | ||
FilePath path = null; |
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.
Bad formating.
"def l = [] \n" + | ||
"node('slaves') {\n" + | ||
" writeYaml file: 'test', data: /['a': ]/ \n" + | ||
" sh 'cat test' \n" + |
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.
There is a feature coming soon to pipeline which stores the parameters of steps, that might risk printing the step to the log, which means your assert might not assert on the thing it think it does.
It would be more precise if you archived the file and read it back in in the test to verify the contents. But it's just a nit.
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.
Will readYaml in every test
a5746eb
to
ef1a671
Compare
Requested changes were adressed. @rsandell, could you review them? |
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.
Sorry for not responding earlier. But I have been waiting for today's security announcement.
Since this has the same security vulnerability as was disclosed in Script Security with groovy.json.JsonOutput.toJson(Object)
as it allows arbitrary get methods to be invoked that a script would normally not be allowed to access.
One way we could solve this would be to only allow the step to take a Map
. The other would be to somehow either look at the classloader to see if it is an object declared in the script or a library or to inspect the object to see if all get methods are whitelisted before proceeding. Or maybe the yaml library has a filtering option where we could filter only whitelisted getters somehow.
Completely understandable, better block a bug than fix it at a later stage. Have added a recursive (:imp:) isValidObjectType method to check wether the object to dump is "safe". WDYT? |
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.
Besides my comments it looks good to me.
Just would like someone from the Jenkins cert team to take another look in case I've missed something.
Boolean ret = true; | ||
Set entry = ((Map) obj).entrySet(); | ||
Iterator iterator = entry.iterator(); | ||
while (iterator.hasNext() && ret) { |
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 looks a bit convoluted, something like this would be more readable and simpler I think
for (Map.Entry entry : map.entrySet()) {
if (!isValidObject(entry.getKey()) || !isValidObject(entry.getValue())) {
return false;
}
}
It also seems like you are overwriting the ret
var every time in the loop, so effectively you are only checking the last entry in the map which my suggestion also solves.
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.
True that, Its result of a late commit. Will fix it.
} else if (obj instanceof Collection) { | ||
Boolean ret = true; | ||
Iterator iterator = ((Collection) obj).iterator(); | ||
while (iterator.hasNext() && ret) { |
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.
Same simplification and issue here as for the Map.
Suggestion:
for (Object o : ((Collection)obj)) {
if (!isValidObject(o)) {
return 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.
ditto
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 feature itself looks good, but I am very aware about the isValidObjectType
implementation
pom.xml
Outdated
<pluginRepositories> | ||
<pluginRepository> | ||
<id>repo.jenkins-ci.org</id> | ||
<url>http://repo.jenkins-ci.org/public/</url> |
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.
https 🐋
* Writes a yaml file from the workspace. | ||
* | ||
* @author Javier DELGADO <witokondoria@gmail.com>. | ||
*/ |
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.
since TODO
would be useful since we make attempts to visualize extension javadocs
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.
not needed. it's not present in any other of the steps.
|
||
@DataBoundConstructor | ||
public WriteYamlStep(@Nonnull String file, @Nonnull Object data) { | ||
if (file == null) { |
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.
StringUtils.isBlank()
if (file == null) { | ||
throw new IllegalArgumentException("file parameter must be provided to writeYaml"); | ||
} | ||
this.file = 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.
truncate spaces?
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.
Does it also make sense to verify the patch and to ensure nobody passes an absolute one or a relative with traversal to upper levels?
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.
want to trim the string? Forcing a path from within the current current workspace seems fine
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.
From the writeFile Step, paths are not verified (so traversal is also possible).
Would you prefer a higer level implementation for this check?
* | ||
* @param file file name | ||
*/ | ||
public void setFile(String 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.
Do you need setters? If no, I would advice to either remove them and make the fields final OR to convert the class to @DataBoundSetter
s
(obj instanceof URL) || (obj instanceof Calendar) || | ||
(obj instanceof Date) || (obj instanceof UUID) || | ||
(obj == null)) { | ||
return 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.
It is strange, error-prone (E.g. GString, Long, etc.) and ineffective. Why would you need it?
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.
Its not a complete and final list, but a one less strict than plain Maps, with objects already whitelisted when toJson invocations:
Long is covered by Number
GStrings hasnt been even tested :(
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.
My guess is that the GString
s will be evaluated/expanded in CPS/sandbox before entering the java context, but it needs to be tested non the less.
something like:
writeYaml data: "${currentBuild.rawBuild}", file: 'data'
might be enough
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.
will add tests tomorrow!
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.
Haven't been able to break this in some limited testing as indicated, but that's not exactly a strong endorsement :-/
file.title=File | ||
file.description=File to save as YAML | ||
text.title=Data | ||
text.description=Object to serialize yo YAML |
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.
Yo dawg, I heard yo and yo dawg like yo yos.
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.
LOL, that made my afternoon
private boolean isValidObjectType(Object obj) { | ||
if ((obj instanceof Boolean) || (obj instanceof Character) || | ||
(obj instanceof Number) || (obj instanceof String) || | ||
(obj instanceof URL) || (obj instanceof Calendar) || |
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 had some concerns about this, but it seems it's safe enough:
https://bitbucket.org/asomov/snakeyaml/src/6c6516c003eb4902a0c4c308100c26b99e2ef99c/src/main/java/org/yaml/snakeyaml/representer/SafeRepresenter.java?at=default&fileviewer=file-view-default#SafeRepresenter.java-331
@@ -175,4 +175,11 @@ | |||
<url>https://github.com/jenkinsci/pipeline-utility-steps-plugin</url> | |||
<tag>HEAD</tag> | |||
</scm> | |||
|
|||
<pluginRepositories> |
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.
Time for a new parent pom before trying to fix this.
Most of the changes were adressed (path check is unimplemented). Im willing to squash the commits in one, but have left all of them to easen reviews. |
Delegates to snakeyaml the task of serializing any Object to a yaml file