Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ credentials:
scope: SYSTEM
id: "i<3GitLab"
token: "glpat-XfsqZvVtAx5YCph5bq3r" # gitlab personal access token
- gitlabGroupAccessToken:
scope: SYSTEM
id: "i<3GitLab"
token: "glgat-XfsqZvVtAx5YCph5bq3r" # gitlab group access token

unclassified:
gitLabServers:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ public SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull
public SCMFileSystem build(@NonNull SCMSource source, @NonNull SCMHead head, @CheckForNull SCMRevision rev)
throws IOException, InterruptedException {
GitLabSCMSource gitlabScmSource = (GitLabSCMSource) source;
GitLabApi gitLabApi = apiBuilder(source.getOwner(), gitlabScmSource.getServerName());
GitLabApi gitLabApi =
apiBuilder(source.getOwner(), gitlabScmSource.getServerName(), gitlabScmSource.getCredentialsId());
String projectPath = gitlabScmSource.getProjectPath();
return build(head, rev, gitLabApi, projectPath);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardCredentials;
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
Expand Down Expand Up @@ -198,7 +197,7 @@ public void setTraits(@CheckForNull SCMTrait[] traits) {

private GitLabOwner getGitlabOwner(SCMNavigatorOwner owner) {
if (gitlabOwner == null) {
getGitlabOwner(apiBuilder(owner, serverName));
getGitlabOwner(apiBuilder(owner, serverName, credentialsId));
}
return gitlabOwner;
}
Expand Down Expand Up @@ -235,7 +234,7 @@ protected String id() {
public void visitSources(@NonNull final SCMSourceObserver observer) throws IOException, InterruptedException {
GitLabSCMNavigatorContext context = new GitLabSCMNavigatorContext().withTraits(traits);
try (GitLabSCMNavigatorRequest request = context.newRequest(this, observer)) {
GitLabApi gitLabApi = apiBuilder(observer.getContext(), serverName);
GitLabApi gitLabApi = apiBuilder(observer.getContext(), serverName, credentialsId);
getGitlabOwner(gitLabApi);
List<Project> projects;
if (gitlabOwner instanceof GitLabUser) {
Expand Down Expand Up @@ -459,14 +458,15 @@ public static class DescriptorImpl extends SCMNavigatorDescriptor implements Ico

public static FormValidation doCheckProjectOwner(
@AncestorInPath SCMSourceOwner context,
@QueryParameter String credentialsId,
@QueryParameter String projectOwner,
@QueryParameter String serverName) {
if (projectOwner.equals("")) {
return FormValidation.ok();
}
GitLabApi gitLabApi = null;
try {
gitLabApi = apiBuilder(context, serverName);
gitLabApi = apiBuilder(context, serverName, credentialsId);
GitLabOwner gitLabOwner = GitLabOwner.fetchOwner(gitLabApi, projectOwner);
return FormValidation.ok(projectOwner + " is a valid " + gitLabOwner.getWord());
} catch (IllegalStateException e) {
Expand Down Expand Up @@ -552,9 +552,9 @@ public ListBoxModel doFillCredentialsIdItems(
result.includeMatchingAs(
context instanceof Queue.Task ? ((Queue.Task) context).getDefaultAuthentication() : ACL.SYSTEM,
context,
StandardUsernameCredentials.class,
StandardCredentials.class,
fromUri(getServerUrlFromName(serverName)).build(),
GitClient.CREDENTIALS_MATCHER);
CredentialsMatchers.anyOf(GitClient.CREDENTIALS_MATCHER, GitLabServer.CREDENTIALS_MATCHER));
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import com.cloudbees.plugins.credentials.CredentialsMatchers;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardCredentials;
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials;
import edu.umd.cs.findbugs.annotations.NonNull;
Expand All @@ -31,6 +32,7 @@
import hudson.util.ListBoxModel;
import io.jenkins.plugins.gitlabbranchsource.helpers.GitLabAvatar;
import io.jenkins.plugins.gitlabbranchsource.helpers.GitLabLink;
import io.jenkins.plugins.gitlabserverconfig.credentials.GroupAccessToken;
import io.jenkins.plugins.gitlabserverconfig.credentials.PersonalAccessToken;
import io.jenkins.plugins.gitlabserverconfig.servers.GitLabServer;
import io.jenkins.plugins.gitlabserverconfig.servers.GitLabServers;
Expand Down Expand Up @@ -203,7 +205,7 @@ public String getRemote() {

protected Project getGitlabProject() {
if (gitlabProject == null) {
getGitlabProject(apiBuilder(this.getOwner(), serverName));
getGitlabProject(apiBuilder(this.getOwner(), serverName, credentialsId));
}
return gitlabProject;
}
Expand All @@ -226,7 +228,7 @@ protected Project getGitlabProject(GitLabApi gitLabApi) {
public HashMap<String, AccessLevel> getMembers() {
HashMap<String, AccessLevel> members = new HashMap<>();
try {
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName);
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName, credentialsId);
for (Member m : gitLabApi.getProjectApi().getAllMembers(projectPath)) {
members.put(m.getUsername(), m.getAccessLevel());
}
Expand Down Expand Up @@ -261,7 +263,7 @@ public void setTraits(List<SCMSourceTrait> traits) {
protected SCMRevision retrieve(@NonNull SCMHead head, @NonNull TaskListener listener)
throws IOException, InterruptedException {
try {
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName);
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName, credentialsId);
getGitlabProject(gitLabApi);
if (head instanceof BranchSCMHead) {
listener.getLogger().format("Querying the current revision of branch %s...%n", head.getName());
Expand Down Expand Up @@ -323,7 +325,7 @@ protected void retrieve(
@NonNull TaskListener listener)
throws IOException, InterruptedException {
try {
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName);
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName, credentialsId);
getGitlabProject(gitLabApi);
GitLabSCMSourceContext ctx = new GitLabSCMSourceContext(criteria, observer).withTraits(getTraits());
try (GitLabSCMSourceRequest request = ctx.newRequest(this, listener)) {
Expand Down Expand Up @@ -728,7 +730,7 @@ protected SCMProbe createProbe(@NonNull final SCMHead head, SCMRevision revision
if (builder == null) {
throw new AssertionError();
}
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName);
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName, credentialsId);
getGitlabProject(gitLabApi);
final SCMFileSystem fs = builder.build(head, revision, gitLabApi, projectPath);
return new SCMProbe() {
Expand Down Expand Up @@ -786,14 +788,19 @@ public void afterSave() {
}
}

public PersonalAccessToken credentials() {
return CredentialsMatchers.firstOrNull(
lookupCredentials(
PersonalAccessToken.class,
getOwner(),
Jenkins.getAuthentication(),
fromUri(getServerUrlFromName(serverName)).build()),
GitLabServer.CREDENTIALS_MATCHER);
public StandardCredentials credentials() {
List<StandardCredentials> list = new ArrayList<>();
list.addAll(lookupCredentials(
PersonalAccessToken.class,
getOwner(),
Jenkins.getAuthentication(),
fromUri(getServerUrlFromName(serverName)).build()));
list.addAll(lookupCredentials(
GroupAccessToken.class,
getOwner(),
Jenkins.getAuthentication(),
fromUri(getServerUrlFromName(serverName)).build()));
return CredentialsMatchers.firstOrNull(list, GitLabServer.CREDENTIALS_MATCHER);
}

@Symbol("gitlab")
Expand Down Expand Up @@ -865,13 +872,14 @@ public ListBoxModel doFillCredentialsIdItems(
context,
StandardUsernameCredentials.class,
fromUri(getServerUrlFromName(serverName)).build(),
GitClient.CREDENTIALS_MATCHER);
CredentialsMatchers.anyOf(GitClient.CREDENTIALS_MATCHER, GitLabServer.CREDENTIALS_MATCHER));
return result;
}

public long getProjectId(
@AncestorInPath SCMSourceOwner context,
@QueryParameter String projectPath,
@QueryParameter String credentialsId,
@QueryParameter String serverName) {
List<GitLabServer> gitLabServers = GitLabServers.get().getServers();
if (gitLabServers.size() == 0) {
Expand All @@ -880,9 +888,9 @@ public long getProjectId(
try {
GitLabApi gitLabApi;
if (StringUtils.isBlank(serverName)) {
gitLabApi = apiBuilder(context, gitLabServers.get(0).getName());
gitLabApi = apiBuilder(context, gitLabServers.get(0).getName(), credentialsId);
} else {
gitLabApi = apiBuilder(context, serverName);
gitLabApi = apiBuilder(context, serverName, credentialsId);
}
if (StringUtils.isNotBlank(projectPath)) {
return gitLabApi.getProjectApi().getProject(projectPath).getId();
Expand All @@ -895,6 +903,7 @@ public long getProjectId(

public ListBoxModel doFillProjectPathItems(
@AncestorInPath SCMSourceOwner context,
@QueryParameter String credentialsId,
@QueryParameter String serverName,
@QueryParameter String projectOwner) {
List<GitLabServer> gitLabServers = GitLabServers.get().getServers();
Expand All @@ -905,9 +914,9 @@ public ListBoxModel doFillProjectPathItems(
try {
GitLabApi gitLabApi;
if (serverName.equals("")) {
gitLabApi = apiBuilder(context, gitLabServers.get(0).getName());
gitLabApi = apiBuilder(context, gitLabServers.get(0).getName(), credentialsId);
} else {
gitLabApi = apiBuilder(context, serverName);
gitLabApi = apiBuilder(context, serverName, credentialsId);
}

if (projectOwner.equals("")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
package io.jenkins.plugins.gitlabbranchsource.helpers;

import static com.cloudbees.plugins.credentials.CredentialsMatchers.withId;
import static com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials;
import static com.cloudbees.plugins.credentials.domains.URIRequirementBuilder.fromUri;
import static org.apache.commons.lang.StringUtils.defaultIfBlank;

import com.cloudbees.plugins.credentials.CredentialsMatchers;
import com.cloudbees.plugins.credentials.common.StandardCredentials;
import com.damnhandy.uri.template.UriTemplate;
import com.damnhandy.uri.template.UriTemplateBuilder;
import com.damnhandy.uri.template.impl.Operator;
import hudson.ProxyConfiguration;
import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.security.ACL;
import hudson.security.AccessControlled;
import io.jenkins.plugins.gitlabserverconfig.credentials.GroupAccessToken;
import io.jenkins.plugins.gitlabserverconfig.credentials.PersonalAccessToken;
import io.jenkins.plugins.gitlabserverconfig.servers.GitLabServer;
import io.jenkins.plugins.gitlabserverconfig.servers.GitLabServers;
Expand All @@ -15,17 +25,22 @@
import java.util.Map;
import java.util.regex.Pattern;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jgit.annotations.NonNull;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.ProxyClientConfig;
import org.jenkinsci.plugins.plaincredentials.StringCredentials;

public class GitLabHelper {

public static GitLabApi apiBuilder(AccessControlled context, String serverName) {
public static GitLabApi apiBuilder(AccessControlled context, String serverName, String credentialsId) {
return apiBuilder(context, serverName, getCredential(credentialsId, serverName, context));
}

public static GitLabApi apiBuilder(AccessControlled context, String serverName, StandardCredentials credential) {
GitLabServer server = GitLabServers.get().findServer(serverName);
if (server != null) {
StandardCredentials credentials = server.getCredentials(context);
StandardCredentials credentials = credential != null ? credential : server.getCredentials(context);
String serverUrl = server.getServerUrl();
String privateToken = getPrivateTokenAsPlainText(credentials);
if (privateToken.equals(GitLabServer.EMPTY_TOKEN)) {
Expand Down Expand Up @@ -106,6 +121,9 @@ public static String getPrivateTokenAsPlainText(StandardCredentials credentials)
if (credentials instanceof PersonalAccessToken) {
privateToken = ((PersonalAccessToken) credentials).getToken().getPlainText();
}
if (credentials instanceof GroupAccessToken) {
privateToken = ((GroupAccessToken) credentials).getToken().getPlainText();
}
if (credentials instanceof StringCredentials) {
privateToken = ((StringCredentials) credentials).getSecret().getPlainText();
}
Expand Down Expand Up @@ -148,4 +166,32 @@ public static UriTemplate commitUriTemplate(String serverNameOrUrl) {
public static String[] splitPath(String path) {
return path.split(Operator.PATH.getSeparator());
}

public static StandardCredentials getCredential(String credentialsId, String serverName, AccessControlled context) {
if (StringUtils.isNotBlank(credentialsId)) {
if (context instanceof ItemGroup) {
return CredentialsMatchers.firstOrNull(
lookupCredentials(
StandardCredentials.class,
(ItemGroup) context,
ACL.SYSTEM,
fromUri(defaultIfBlank(
getServerUrlFromName(serverName), GitLabServer.GITLAB_SERVER_URL))
.build()),
withId(credentialsId));
} else {
return CredentialsMatchers.firstOrNull(
lookupCredentials(
StandardCredentials.class,
(Item) context,
ACL.SYSTEM,
fromUri(defaultIfBlank(
getServerUrlFromName(serverName), GitLabServer.GITLAB_SERVER_URL))
.build()),
withId(credentialsId));
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ private static void logComment(Run<?, ?> build, TaskListener listener) {
String suffix = " - [Details](" + url + ")";
SCMRevision revision = SCMRevisionAction.getRevision(source, build);
try {
GitLabApi gitLabApi = GitLabHelper.apiBuilder(build.getParent(), source.getServerName());
GitLabApi gitLabApi =
GitLabHelper.apiBuilder(build.getParent(), source.getServerName(), source.getCredentialsId());
String sudoUsername = sourceContext.getSudoUser();
if (!sudoUsername.isEmpty()) {
gitLabApi.sudo(sudoUsername);
Expand Down Expand Up @@ -375,7 +376,8 @@ private static void sendNotifications(Run<?, ?> build, TaskListener listener, Bo
}
}
try {
GitLabApi gitLabApi = GitLabHelper.apiBuilder(build.getParent(), source.getServerName());
GitLabApi gitLabApi =
GitLabHelper.apiBuilder(build.getParent(), source.getServerName(), source.getCredentialsId());
LOGGER.log(Level.FINE, String.format("Notifiying commit: %s", hash));

if (revision instanceof MergeRequestSCMRevision) {
Expand Down Expand Up @@ -476,7 +478,8 @@ public void onEnterWaiting(final Queue.WaitingItem wi) {

Constants.CommitBuildState state = Constants.CommitBuildState.PENDING;
try {
GitLabApi gitLabApi = GitLabHelper.apiBuilder(job, source.getServerName());
GitLabApi gitLabApi =
GitLabHelper.apiBuilder(job, source.getServerName(), source.getCredentialsId());
// check are we still the task to set pending
synchronized (resolving) {
if (!nonce.equals(resolving.get(job))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ public HttpResponse doServerList() {

@RequirePOST
public HttpResponse doProjectList(
@AncestorInPath SCMSourceOwner context, @QueryParameter String server, @QueryParameter String owner) {
@AncestorInPath SCMSourceOwner context,
@QueryParameter String server,
@QueryParameter String credentialsId,
@QueryParameter String owner) {
if (!Jenkins.get().hasPermission(Jenkins.MANAGE)) {
return HttpResponses.errorJSON("no permission to get Gitlab server list");
}
Expand All @@ -62,7 +65,7 @@ public HttpResponse doProjectList(

JSONArray servers = new JSONArray();

GitLabApi gitLabApi = GitLabHelper.apiBuilder(context, server);
GitLabApi gitLabApi = GitLabHelper.apiBuilder(context, server, credentialsId);
try {
for (Project project :
gitLabApi.getProjectApi().getUserProjects(owner, new ProjectFilter().withOwned(true))) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.jenkins.plugins.gitlabserverconfig.credentials;

import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.util.Secret;

public interface GroupAccessToken extends StandardUsernamePasswordCredentials {

/**
* Returns the token.
*
* @return the token.
*/
@NonNull
Secret getToken();
}
Loading