Skip to content

Commit 9e482e4

Browse files
authored
Add support for GroupAccessToken credentials, fix credential integration (#479)
1 parent ad1a742 commit 9e482e4

File tree

21 files changed

+357
-58
lines changed

21 files changed

+357
-58
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,10 @@ credentials:
343343
scope: SYSTEM
344344
id: "i<3GitLab"
345345
token: "glpat-XfsqZvVtAx5YCph5bq3r" # gitlab personal access token
346+
- gitlabGroupAccessToken:
347+
scope: SYSTEM
348+
id: "i<3GitLab"
349+
token: "glgat-XfsqZvVtAx5YCph5bq3r" # gitlab group access token
346350
347351
unclassified:
348352
gitLabServers:

src/main/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMFileSystem.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ public SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull
8484
public SCMFileSystem build(@NonNull SCMSource source, @NonNull SCMHead head, @CheckForNull SCMRevision rev)
8585
throws IOException, InterruptedException {
8686
GitLabSCMSource gitlabScmSource = (GitLabSCMSource) source;
87-
GitLabApi gitLabApi = apiBuilder(source.getOwner(), gitlabScmSource.getServerName());
87+
GitLabApi gitLabApi =
88+
apiBuilder(source.getOwner(), gitlabScmSource.getServerName(), gitlabScmSource.getCredentialsId());
8889
String projectPath = gitlabScmSource.getProjectPath();
8990
return build(head, rev, gitLabApi, projectPath);
9091
}

src/main/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMNavigator.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import com.cloudbees.plugins.credentials.CredentialsProvider;
1515
import com.cloudbees.plugins.credentials.common.StandardCredentials;
1616
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
17-
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials;
1817
import edu.umd.cs.findbugs.annotations.CheckForNull;
1918
import edu.umd.cs.findbugs.annotations.NonNull;
2019
import hudson.Extension;
@@ -198,7 +197,7 @@ public void setTraits(@CheckForNull SCMTrait[] traits) {
198197

199198
private GitLabOwner getGitlabOwner(SCMNavigatorOwner owner) {
200199
if (gitlabOwner == null) {
201-
getGitlabOwner(apiBuilder(owner, serverName));
200+
getGitlabOwner(apiBuilder(owner, serverName, credentialsId));
202201
}
203202
return gitlabOwner;
204203
}
@@ -235,7 +234,7 @@ protected String id() {
235234
public void visitSources(@NonNull final SCMSourceObserver observer) throws IOException, InterruptedException {
236235
GitLabSCMNavigatorContext context = new GitLabSCMNavigatorContext().withTraits(traits);
237236
try (GitLabSCMNavigatorRequest request = context.newRequest(this, observer)) {
238-
GitLabApi gitLabApi = apiBuilder(observer.getContext(), serverName);
237+
GitLabApi gitLabApi = apiBuilder(observer.getContext(), serverName, credentialsId);
239238
getGitlabOwner(gitLabApi);
240239
List<Project> projects;
241240
if (gitlabOwner instanceof GitLabUser) {
@@ -459,14 +458,15 @@ public static class DescriptorImpl extends SCMNavigatorDescriptor implements Ico
459458

460459
public static FormValidation doCheckProjectOwner(
461460
@AncestorInPath SCMSourceOwner context,
461+
@QueryParameter String credentialsId,
462462
@QueryParameter String projectOwner,
463463
@QueryParameter String serverName) {
464464
if (projectOwner.equals("")) {
465465
return FormValidation.ok();
466466
}
467467
GitLabApi gitLabApi = null;
468468
try {
469-
gitLabApi = apiBuilder(context, serverName);
469+
gitLabApi = apiBuilder(context, serverName, credentialsId);
470470
GitLabOwner gitLabOwner = GitLabOwner.fetchOwner(gitLabApi, projectOwner);
471471
return FormValidation.ok(projectOwner + " is a valid " + gitLabOwner.getWord());
472472
} catch (IllegalStateException e) {
@@ -552,9 +552,9 @@ public ListBoxModel doFillCredentialsIdItems(
552552
result.includeMatchingAs(
553553
context instanceof Queue.Task ? ((Queue.Task) context).getDefaultAuthentication() : ACL.SYSTEM,
554554
context,
555-
StandardUsernameCredentials.class,
555+
StandardCredentials.class,
556556
fromUri(getServerUrlFromName(serverName)).build(),
557-
GitClient.CREDENTIALS_MATCHER);
557+
CredentialsMatchers.anyOf(GitClient.CREDENTIALS_MATCHER, GitLabServer.CREDENTIALS_MATCHER));
558558
return result;
559559
}
560560

src/main/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMSource.java

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import com.cloudbees.plugins.credentials.CredentialsMatchers;
1515
import com.cloudbees.plugins.credentials.CredentialsProvider;
16+
import com.cloudbees.plugins.credentials.common.StandardCredentials;
1617
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
1718
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials;
1819
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -32,6 +33,7 @@
3233
import io.jenkins.plugins.gitlabbranchsource.helpers.GitLabAvatar;
3334
import io.jenkins.plugins.gitlabbranchsource.helpers.GitLabLink;
3435
import io.jenkins.plugins.gitlabbranchsource.helpers.Sleeper;
36+
import io.jenkins.plugins.gitlabserverconfig.credentials.GroupAccessToken;
3537
import io.jenkins.plugins.gitlabserverconfig.credentials.PersonalAccessToken;
3638
import io.jenkins.plugins.gitlabserverconfig.servers.GitLabServer;
3739
import io.jenkins.plugins.gitlabserverconfig.servers.GitLabServers;
@@ -208,7 +210,7 @@ public String getRemote() {
208210

209211
protected Project getGitlabProject() {
210212
if (gitlabProject == null) {
211-
getGitlabProject(apiBuilder(this.getOwner(), serverName));
213+
getGitlabProject(apiBuilder(this.getOwner(), serverName, credentialsId));
212214
}
213215
return gitlabProject;
214216
}
@@ -247,7 +249,7 @@ private List<Member> getMembersWithRetries() throws GitLabApiException, Interrup
247249
int delay = INITIAL_DELAY_MS;
248250
int attemptNb = 0;
249251
final Sleeper sleeper = new Sleeper();
250-
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName);
252+
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName, credentialsId);
251253
while (true) {
252254
try {
253255
return gitLabApi.getProjectApi().getAllMembers(projectPath);
@@ -300,7 +302,7 @@ public void setTraits(List<SCMSourceTrait> traits) {
300302
protected SCMRevision retrieve(@NonNull SCMHead head, @NonNull TaskListener listener)
301303
throws IOException, InterruptedException {
302304
try {
303-
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName);
305+
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName, credentialsId);
304306
getGitlabProject(gitLabApi);
305307
if (head instanceof BranchSCMHead) {
306308
listener.getLogger().format("Querying the current revision of branch %s...%n", head.getName());
@@ -362,7 +364,7 @@ protected void retrieve(
362364
@NonNull TaskListener listener)
363365
throws IOException, InterruptedException {
364366
try {
365-
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName);
367+
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName, credentialsId);
366368
getGitlabProject(gitLabApi);
367369
GitLabSCMSourceContext ctx = new GitLabSCMSourceContext(criteria, observer).withTraits(getTraits());
368370
try (GitLabSCMSourceRequest request = ctx.newRequest(this, listener)) {
@@ -774,7 +776,7 @@ protected SCMProbe createProbe(@NonNull final SCMHead head, SCMRevision revision
774776
if (builder == null) {
775777
throw new AssertionError();
776778
}
777-
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName);
779+
GitLabApi gitLabApi = apiBuilder(this.getOwner(), serverName, credentialsId);
778780
getGitlabProject(gitLabApi);
779781
final SCMFileSystem fs = builder.build(head, revision, gitLabApi, projectPath);
780782
return new SCMProbe() {
@@ -832,14 +834,19 @@ public void afterSave() {
832834
}
833835
}
834836

835-
public PersonalAccessToken credentials() {
836-
return CredentialsMatchers.firstOrNull(
837-
lookupCredentials(
838-
PersonalAccessToken.class,
839-
getOwner(),
840-
Jenkins.getAuthentication(),
841-
fromUri(getServerUrlFromName(serverName)).build()),
842-
GitLabServer.CREDENTIALS_MATCHER);
837+
public StandardCredentials credentials() {
838+
List<StandardCredentials> list = new ArrayList<>();
839+
list.addAll(lookupCredentials(
840+
PersonalAccessToken.class,
841+
getOwner(),
842+
Jenkins.getAuthentication(),
843+
fromUri(getServerUrlFromName(serverName)).build()));
844+
list.addAll(lookupCredentials(
845+
GroupAccessToken.class,
846+
getOwner(),
847+
Jenkins.getAuthentication(),
848+
fromUri(getServerUrlFromName(serverName)).build()));
849+
return CredentialsMatchers.firstOrNull(list, GitLabServer.CREDENTIALS_MATCHER);
843850
}
844851

845852
@Symbol("gitlab")
@@ -911,13 +918,14 @@ public ListBoxModel doFillCredentialsIdItems(
911918
context,
912919
StandardUsernameCredentials.class,
913920
fromUri(getServerUrlFromName(serverName)).build(),
914-
GitClient.CREDENTIALS_MATCHER);
921+
CredentialsMatchers.anyOf(GitClient.CREDENTIALS_MATCHER, GitLabServer.CREDENTIALS_MATCHER));
915922
return result;
916923
}
917924

918925
public long getProjectId(
919926
@AncestorInPath SCMSourceOwner context,
920927
@QueryParameter String projectPath,
928+
@QueryParameter String credentialsId,
921929
@QueryParameter String serverName) {
922930
List<GitLabServer> gitLabServers = GitLabServers.get().getServers();
923931
if (gitLabServers.size() == 0) {
@@ -926,9 +934,9 @@ public long getProjectId(
926934
try {
927935
GitLabApi gitLabApi;
928936
if (StringUtils.isBlank(serverName)) {
929-
gitLabApi = apiBuilder(context, gitLabServers.get(0).getName());
937+
gitLabApi = apiBuilder(context, gitLabServers.get(0).getName(), credentialsId);
930938
} else {
931-
gitLabApi = apiBuilder(context, serverName);
939+
gitLabApi = apiBuilder(context, serverName, credentialsId);
932940
}
933941
if (StringUtils.isNotBlank(projectPath)) {
934942
return gitLabApi.getProjectApi().getProject(projectPath).getId();
@@ -941,6 +949,7 @@ public long getProjectId(
941949

942950
public ListBoxModel doFillProjectPathItems(
943951
@AncestorInPath SCMSourceOwner context,
952+
@QueryParameter String credentialsId,
944953
@QueryParameter String serverName,
945954
@QueryParameter String projectOwner) {
946955
List<GitLabServer> gitLabServers = GitLabServers.get().getServers();
@@ -951,9 +960,9 @@ public ListBoxModel doFillProjectPathItems(
951960
try {
952961
GitLabApi gitLabApi;
953962
if (serverName.equals("")) {
954-
gitLabApi = apiBuilder(context, gitLabServers.get(0).getName());
963+
gitLabApi = apiBuilder(context, gitLabServers.get(0).getName(), credentialsId);
955964
} else {
956-
gitLabApi = apiBuilder(context, serverName);
965+
gitLabApi = apiBuilder(context, serverName, credentialsId);
957966
}
958967

959968
if (projectOwner.equals("")) {

src/main/java/io/jenkins/plugins/gitlabbranchsource/helpers/GitLabHelper.java

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
package io.jenkins.plugins.gitlabbranchsource.helpers;
22

3+
import static com.cloudbees.plugins.credentials.CredentialsMatchers.withId;
4+
import static com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials;
5+
import static com.cloudbees.plugins.credentials.domains.URIRequirementBuilder.fromUri;
6+
7+
import com.cloudbees.plugins.credentials.CredentialsMatchers;
38
import com.cloudbees.plugins.credentials.common.StandardCredentials;
49
import com.damnhandy.uri.template.UriTemplate;
510
import com.damnhandy.uri.template.UriTemplateBuilder;
611
import com.damnhandy.uri.template.impl.Operator;
712
import hudson.ProxyConfiguration;
13+
import hudson.model.Item;
14+
import hudson.model.ItemGroup;
15+
import hudson.security.ACL;
816
import hudson.security.AccessControlled;
17+
import io.jenkins.plugins.gitlabserverconfig.credentials.GroupAccessToken;
918
import io.jenkins.plugins.gitlabserverconfig.credentials.PersonalAccessToken;
1019
import io.jenkins.plugins.gitlabserverconfig.servers.GitLabServer;
1120
import io.jenkins.plugins.gitlabserverconfig.servers.GitLabServers;
@@ -15,17 +24,22 @@
1524
import java.util.Map;
1625
import java.util.regex.Pattern;
1726
import jenkins.model.Jenkins;
27+
import org.apache.commons.lang3.StringUtils;
1828
import org.eclipse.jgit.annotations.NonNull;
1929
import org.gitlab4j.api.GitLabApi;
2030
import org.gitlab4j.api.ProxyClientConfig;
2131
import org.jenkinsci.plugins.plaincredentials.StringCredentials;
2232

2333
public class GitLabHelper {
2434

25-
public static GitLabApi apiBuilder(AccessControlled context, String serverName) {
35+
public static GitLabApi apiBuilder(AccessControlled context, String serverName, String credentialsId) {
36+
return apiBuilder(context, serverName, getCredential(credentialsId, serverName, context));
37+
}
38+
39+
public static GitLabApi apiBuilder(AccessControlled context, String serverName, StandardCredentials credential) {
2640
GitLabServer server = GitLabServers.get().findServer(serverName);
2741
if (server != null) {
28-
StandardCredentials credentials = server.getCredentials(context);
42+
StandardCredentials credentials = credential != null ? credential : server.getCredentials(context);
2943
String serverUrl = server.getServerUrl();
3044
String privateToken = getPrivateTokenAsPlainText(credentials);
3145
if (privateToken.equals(GitLabServer.EMPTY_TOKEN)) {
@@ -106,6 +120,9 @@ public static String getPrivateTokenAsPlainText(StandardCredentials credentials)
106120
if (credentials instanceof PersonalAccessToken) {
107121
privateToken = ((PersonalAccessToken) credentials).getToken().getPlainText();
108122
}
123+
if (credentials instanceof GroupAccessToken) {
124+
privateToken = ((GroupAccessToken) credentials).getToken().getPlainText();
125+
}
109126
if (credentials instanceof StringCredentials) {
110127
privateToken = ((StringCredentials) credentials).getSecret().getPlainText();
111128
}
@@ -148,4 +165,32 @@ public static UriTemplate commitUriTemplate(String serverNameOrUrl) {
148165
public static String[] splitPath(String path) {
149166
return path.split(Operator.PATH.getSeparator());
150167
}
168+
169+
public static StandardCredentials getCredential(String credentialsId, String serverName, AccessControlled context) {
170+
if (StringUtils.isNotBlank(credentialsId)) {
171+
if (context instanceof ItemGroup) {
172+
return CredentialsMatchers.firstOrNull(
173+
lookupCredentials(
174+
StandardCredentials.class,
175+
(ItemGroup) context,
176+
ACL.SYSTEM,
177+
fromUri(StringUtils.defaultIfBlank(
178+
getServerUrlFromName(serverName), GitLabServer.GITLAB_SERVER_URL))
179+
.build()),
180+
withId(credentialsId));
181+
} else {
182+
return CredentialsMatchers.firstOrNull(
183+
lookupCredentials(
184+
StandardCredentials.class,
185+
(Item) context,
186+
ACL.SYSTEM,
187+
fromUri(StringUtils.defaultIfBlank(
188+
getServerUrlFromName(serverName), GitLabServer.GITLAB_SERVER_URL))
189+
.build()),
190+
withId(credentialsId));
191+
}
192+
}
193+
194+
return null;
195+
}
151196
}

src/main/java/io/jenkins/plugins/gitlabbranchsource/helpers/GitLabPipelineStatusNotifier.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ private static void logComment(Run<?, ?> build, TaskListener listener) {
207207
String suffix = " - [Details](" + url + ")";
208208
SCMRevision revision = SCMRevisionAction.getRevision(source, build);
209209
try {
210-
GitLabApi gitLabApi = GitLabHelper.apiBuilder(build.getParent(), source.getServerName());
210+
GitLabApi gitLabApi =
211+
GitLabHelper.apiBuilder(build.getParent(), source.getServerName(), source.getCredentialsId());
211212
String sudoUsername = sourceContext.getSudoUser();
212213
if (!sudoUsername.isEmpty()) {
213214
gitLabApi.sudo(sudoUsername);
@@ -375,7 +376,8 @@ private static void sendNotifications(Run<?, ?> build, TaskListener listener, Bo
375376
}
376377
}
377378
try {
378-
GitLabApi gitLabApi = GitLabHelper.apiBuilder(build.getParent(), source.getServerName());
379+
GitLabApi gitLabApi =
380+
GitLabHelper.apiBuilder(build.getParent(), source.getServerName(), source.getCredentialsId());
379381
LOGGER.log(Level.FINE, String.format("Notifiying commit: %s", hash));
380382

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

477479
Constants.CommitBuildState state = Constants.CommitBuildState.PENDING;
478480
try {
479-
GitLabApi gitLabApi = GitLabHelper.apiBuilder(job, source.getServerName());
481+
GitLabApi gitLabApi =
482+
GitLabHelper.apiBuilder(job, source.getServerName(), source.getCredentialsId());
480483
// check are we still the task to set pending
481484
synchronized (resolving) {
482485
if (!nonce.equals(resolving.get(job))) {

src/main/java/io/jenkins/plugins/gitlabserverconfig/action/GitlabAction.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ public HttpResponse doServerList() {
5151

5252
@RequirePOST
5353
public HttpResponse doProjectList(
54-
@AncestorInPath SCMSourceOwner context, @QueryParameter String server, @QueryParameter String owner) {
54+
@AncestorInPath SCMSourceOwner context,
55+
@QueryParameter String server,
56+
@QueryParameter String credentialsId,
57+
@QueryParameter String owner) {
5558
if (!Jenkins.get().hasPermission(Jenkins.MANAGE)) {
5659
return HttpResponses.errorJSON("no permission to get Gitlab server list");
5760
}
@@ -62,7 +65,7 @@ public HttpResponse doProjectList(
6265

6366
JSONArray servers = new JSONArray();
6467

65-
GitLabApi gitLabApi = GitLabHelper.apiBuilder(context, server);
68+
GitLabApi gitLabApi = GitLabHelper.apiBuilder(context, server, credentialsId);
6669
try {
6770
for (Project project :
6871
gitLabApi.getProjectApi().getUserProjects(owner, new ProjectFilter().withOwned(true))) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package io.jenkins.plugins.gitlabserverconfig.credentials;
2+
3+
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
4+
import edu.umd.cs.findbugs.annotations.NonNull;
5+
import hudson.util.Secret;
6+
7+
public interface GroupAccessToken extends StandardUsernamePasswordCredentials {
8+
9+
/**
10+
* Returns the token.
11+
*
12+
* @return the token.
13+
*/
14+
@NonNull
15+
Secret getToken();
16+
}

0 commit comments

Comments
 (0)