Skip to content
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

[JENKINS-48954] - Whitelist model objects #18

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Jenkinsfile
@@ -1 +1 @@
buildPlugin()
buildPlugin(jenkinsVersions: [null, '2.102'])
Copy link
Member

Choose a reason for hiding this comment

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

Good, we should start doing this in lots of plugins…

4 changes: 2 additions & 2 deletions pom.xml
Expand Up @@ -3,7 +3,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>2.31</version>
<version>3.2</version>
<relativePath />
</parent>

Expand All @@ -22,7 +22,7 @@
<url>https://wiki.jenkins-ci.org/display/JENKINS/GitHub+API+Plugin</url>

<properties>
<jenkins.version>1.615</jenkins.version>
<jenkins.version>1.625.3</jenkins.version>
<java.level>7</java.level>
<no-test-jar>false</no-test-jar>
</properties>
Expand Down
179 changes: 179 additions & 0 deletions src/main/resources/META-INF/hudson.remoting.ClassFilter
@@ -0,0 +1,179 @@
# Generated by GitHubAPIClassListerTest
org.kohsuke.github.AbuseLimitHandler
Copy link
Member

Choose a reason for hiding this comment

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

Delete this and just add Jenkins-ClassFilter-Whitelisted to the library.

org.kohsuke.github.AbuseLimitHandler$1
org.kohsuke.github.AbuseLimitHandler$2
org.kohsuke.github.DeleteToken
org.kohsuke.github.GHAsset
org.kohsuke.github.GHAuthorization
org.kohsuke.github.GHAuthorization$App
org.kohsuke.github.GHBlob
org.kohsuke.github.GHBlobBuilder
org.kohsuke.github.GHBranch
org.kohsuke.github.GHBranch$1
org.kohsuke.github.GHBranch$Commit
org.kohsuke.github.GHBranchProtection
org.kohsuke.github.GHBranchProtection$EnforceAdmins
org.kohsuke.github.GHBranchProtection$RequiredReviews
org.kohsuke.github.GHBranchProtection$RequiredStatusChecks
org.kohsuke.github.GHBranchProtection$Restrictions
org.kohsuke.github.GHBranchProtectionBuilder
org.kohsuke.github.GHBranchProtectionBuilder$1
org.kohsuke.github.GHBranchProtectionBuilder$Restrictions
org.kohsuke.github.GHBranchProtectionBuilder$StatusChecks
org.kohsuke.github.GHCommit
org.kohsuke.github.GHCommit$File
org.kohsuke.github.GHCommit$GHAuthor
org.kohsuke.github.GHCommit$Parent
org.kohsuke.github.GHCommit$ShortInfo
org.kohsuke.github.GHCommit$ShortInfo$Tree
org.kohsuke.github.GHCommit$Stats
org.kohsuke.github.GHCommit$User
org.kohsuke.github.GHCommitBuilder
org.kohsuke.github.GHCommitBuilder$1
org.kohsuke.github.GHCommitBuilder$UserInfo
org.kohsuke.github.GHCommitComment
org.kohsuke.github.GHCommitPointer
org.kohsuke.github.GHCommitQueryBuilder
org.kohsuke.github.GHCommitSearchBuilder
org.kohsuke.github.GHCommitSearchBuilder$CommitSearchResult
org.kohsuke.github.GHCommitStatus
org.kohsuke.github.GHCompare
org.kohsuke.github.GHCompare$Commit
org.kohsuke.github.GHCompare$InnerCommit
org.kohsuke.github.GHCompare$Tree
org.kohsuke.github.GHCompare$User
org.kohsuke.github.GHContent
org.kohsuke.github.GHContentSearchBuilder
org.kohsuke.github.GHContentSearchBuilder$ContentSearchResult
org.kohsuke.github.GHContentUpdateResponse
org.kohsuke.github.GHContentWithLicense
org.kohsuke.github.GHCreateRepositoryBuilder
org.kohsuke.github.GHDeployKey
org.kohsuke.github.GHDeployment
org.kohsuke.github.GHDeploymentBuilder
org.kohsuke.github.GHDeploymentStatus
org.kohsuke.github.GHDeploymentStatusBuilder
org.kohsuke.github.GHEmail
org.kohsuke.github.GHEventInfo
org.kohsuke.github.GHEventInfo$GHEventRepository
org.kohsuke.github.GHEventPayload
org.kohsuke.github.GHEventPayload$CommitComment
org.kohsuke.github.GHEventPayload$Create
org.kohsuke.github.GHEventPayload$Delete
org.kohsuke.github.GHEventPayload$Deployment
org.kohsuke.github.GHEventPayload$DeploymentStatus
org.kohsuke.github.GHEventPayload$Fork
org.kohsuke.github.GHEventPayload$IssueComment
org.kohsuke.github.GHEventPayload$Ping
org.kohsuke.github.GHEventPayload$Public
org.kohsuke.github.GHEventPayload$PullRequest
org.kohsuke.github.GHEventPayload$Push
org.kohsuke.github.GHEventPayload$Push$PushCommit
org.kohsuke.github.GHEventPayload$Push$Pusher
org.kohsuke.github.GHEventPayload$Repository
org.kohsuke.github.GHGist
org.kohsuke.github.GHGistBuilder
org.kohsuke.github.GHGistFile
org.kohsuke.github.GHHook
org.kohsuke.github.GHHooks
org.kohsuke.github.GHHooks$1
org.kohsuke.github.GHHooks$Context
org.kohsuke.github.GHHooks$OrgContext
org.kohsuke.github.GHHooks$RepoContext
org.kohsuke.github.GHIssue
org.kohsuke.github.GHIssue$Label
org.kohsuke.github.GHIssue$PullRequest
org.kohsuke.github.GHIssueBuilder
org.kohsuke.github.GHIssueComment
org.kohsuke.github.GHIssueSearchBuilder
org.kohsuke.github.GHIssueSearchBuilder$IssueSearchResult
org.kohsuke.github.GHKey
org.kohsuke.github.GHLabel
org.kohsuke.github.GHLicense
org.kohsuke.github.GHMembership
org.kohsuke.github.GHMilestone
org.kohsuke.github.GHMyself
org.kohsuke.github.GHNotificationStream
org.kohsuke.github.GHObject
org.kohsuke.github.GHObject$1
org.kohsuke.github.GHObject$2
org.kohsuke.github.GHOrgHook
org.kohsuke.github.GHOrganization
org.kohsuke.github.GHPermission
org.kohsuke.github.GHPerson
org.kohsuke.github.GHPersonSet
org.kohsuke.github.GHPullRequest
org.kohsuke.github.GHPullRequest$DraftReviewComment
org.kohsuke.github.GHPullRequestCommitDetail
org.kohsuke.github.GHPullRequestCommitDetail$Authorship
org.kohsuke.github.GHPullRequestCommitDetail$Commit
org.kohsuke.github.GHPullRequestCommitDetail$CommitPointer
org.kohsuke.github.GHPullRequestCommitDetail$Tree
org.kohsuke.github.GHPullRequestFileDetail
org.kohsuke.github.GHPullRequestQueryBuilder
org.kohsuke.github.GHPullRequestReview
org.kohsuke.github.GHPullRequestReviewComment
org.kohsuke.github.GHQueryBuilder
org.kohsuke.github.GHRateLimit
org.kohsuke.github.GHReaction
org.kohsuke.github.GHRef
org.kohsuke.github.GHRef$GHObject
org.kohsuke.github.GHRelease
org.kohsuke.github.GHReleaseBuilder
org.kohsuke.github.GHReleaseUpdater
org.kohsuke.github.GHRepoHook
org.kohsuke.github.GHRepository
org.kohsuke.github.GHRepository$Contributor
org.kohsuke.github.GHRepository$GHRepoPermission
org.kohsuke.github.GHRepositoryCloneTraffic
org.kohsuke.github.GHRepositoryCloneTraffic$DailyInfo
org.kohsuke.github.GHRepositorySearchBuilder
org.kohsuke.github.GHRepositorySearchBuilder$RepositorySearchResult
org.kohsuke.github.GHRepositoryTraffic
org.kohsuke.github.GHRepositoryTraffic$DailyInfo
org.kohsuke.github.GHRepositoryViewTraffic
org.kohsuke.github.GHRepositoryViewTraffic$DailyInfo
org.kohsuke.github.GHSearchBuilder
org.kohsuke.github.GHStargazer
org.kohsuke.github.GHSubscription
org.kohsuke.github.GHTag
org.kohsuke.github.GHTagObject
org.kohsuke.github.GHTeam
org.kohsuke.github.GHThread
org.kohsuke.github.GHThread$Subject
org.kohsuke.github.GHTree
org.kohsuke.github.GHTreeBuilder
org.kohsuke.github.GHTreeBuilder$1
org.kohsuke.github.GHTreeBuilder$TreeEntry
org.kohsuke.github.GHTreeEntry
org.kohsuke.github.GHUser
org.kohsuke.github.GHUserSearchBuilder
org.kohsuke.github.GHUserSearchBuilder$UserSearchResult
org.kohsuke.github.GHVerifiedKey
org.kohsuke.github.GitHub
org.kohsuke.github.GitHub$GHApiInfo
org.kohsuke.github.GitHubBuilder
org.kohsuke.github.GitHubBuilder$1
org.kohsuke.github.GitUser
org.kohsuke.github.HttpConnector$1
org.kohsuke.github.HttpConnector$2
org.kohsuke.github.JsonRateLimit
org.kohsuke.github.PagedIterable
org.kohsuke.github.PagedIterator
org.kohsuke.github.PagedSearchIterable
org.kohsuke.github.Previews
org.kohsuke.github.RateLimitHandler
org.kohsuke.github.RateLimitHandler$1
org.kohsuke.github.RateLimitHandler$2
org.kohsuke.github.Requester
org.kohsuke.github.Requester$1
org.kohsuke.github.Requester$Entry
org.kohsuke.github.Requester$PagingIterator
org.kohsuke.github.SearchResult
org.kohsuke.github.extras.ImpatientHttpConnector
org.kohsuke.github.extras.OkHttp3Connector
org.kohsuke.github.extras.OkHttpConnector

# Manual exceptions
## of type class java.util.AbstractSet - serialization is fine
org.kohsuke.github.GHRepository$15
115 changes: 115 additions & 0 deletions src/test/java/jenkins/plugins/github/api/ClassFilterTest.java
@@ -0,0 +1,115 @@
/*
* The MIT License
*
* Copyright 2018 CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package jenkins.plugins.github.api;

import hudson.XmlFile;
import org.apache.commons.io.IOUtils;
import org.junit.AssumptionViolatedException;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.jvnet.hudson.test.JenkinsRule;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
* Verifies that the whitelisted classes can be actually saved on disk.
Copy link
Member

Choose a reason for hiding this comment

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

I do not understand the purpose of this test. Of course if you add a whitelist entry for something, it can be saved. What does this prove?

*/
@RunWith(Parameterized.class)
public class ClassFilterTest {

@ClassRule
public static JenkinsRule j = new JenkinsRule();

@ClassRule
public static TemporaryFolder tmp = new TemporaryFolder();

private final String className;

public ClassFilterTest(String className) {
this.className = className;
}

@Override
public String toString() {
return super.toString() + " " + className;
}

public static Set<String> readWhitelist() throws AssertionError {
HashSet<String> classes = new HashSet<>();

try (InputStream is = ClassFilterTest.class.getResourceAsStream("/META-INF/hudson.remoting.ClassFilter")) {
for (String line : IOUtils.readLines(is, StandardCharsets.UTF_8)) {
if (line.matches("#.*|\\s*")) { // skip comments
continue;
} else if (line.endsWith(".*")) { // regexp, we assume that it is a pattern like foo.bar.* or foo.bar.Foo.*
throw new AssertionError("Regular expressions are not supported so far");
} else { // just class entry
classes.add(line);
}
}
} catch (IOException ex) {
throw new AssertionError("Failed to read /META-INF/hudson.remoting.ClassFilter", ex);
}

return classes;
}

@Parameterized.Parameters(name = "{index}: class={0}")
public static Collection<String> data() throws AssertionError {
return readWhitelist();
}

@Test
public void testClass() throws AssertionError, IOException {
final Class<?> clazz;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException ex) {
throw new AssertionError("Whitelisted class does not exist", ex);
}

Object obj;
try {
obj = clazz.getConstructor().newInstance();
} catch (NoSuchMethodException ex) {
throw new AssumptionViolatedException("The class has no default constructor. Cannot check its serialization", ex);
} catch (IllegalAccessException | InvocationTargetException | InstantiationException | NoClassDefFoundError ex) {
// NoClassDefFoundError is for OkHttp
throw new AssumptionViolatedException("Cannot instantinate the class", ex);
}

XmlFile f = new XmlFile(new File(tmp.getRoot(), className + ".xml"));
f.write(obj);
}
}