diff --git a/src/main/java/org/jenkinsci/plugins/JiraTestResultReporter/BearerAuthenticationHandler.java b/src/main/java/org/jenkinsci/plugins/JiraTestResultReporter/BearerAuthenticationHandler.java new file mode 100644 index 0000000..d915b8a --- /dev/null +++ b/src/main/java/org/jenkinsci/plugins/JiraTestResultReporter/BearerAuthenticationHandler.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 Atlassian + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jenkinsci.plugins.JiraTestResultReporter; + +import com.atlassian.httpclient.api.Request; +import com.atlassian.jira.rest.client.api.AuthenticationHandler; + +/** + * Handler for Bearer (Token) authentication + */ +public class BearerAuthenticationHandler implements AuthenticationHandler { + + private static final String AUTHORIZATION_HEADER = "Authorization"; + + private final String token; + + public BearerAuthenticationHandler(String token) { + this.token = token; + } + + @Override + public void configure(Request.Builder builder) { + builder.setHeader(AUTHORIZATION_HEADER, "Bearer " + token); + } +} diff --git a/src/main/java/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher.java b/src/main/java/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher.java index 31f9eaa..decbfb1 100644 --- a/src/main/java/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher.java +++ b/src/main/java/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher.java @@ -469,6 +469,7 @@ public JiraTestDataPublisherDescriptor() { private URI jiraUri = null; private String username = null; private Secret password = null; + private boolean useBearerAuth = false; private String defaultSummary; private String defaultDescription; @@ -484,6 +485,10 @@ public Secret getPassword() { return password; } + public boolean getUseBearerAuth() { + return useBearerAuth; + } + public String getJiraUrl() { return jiraUri != null ? jiraUri.toString() : null; } @@ -536,13 +541,23 @@ public MetadataCache.CacheEntry getCacheEntry(String projectKey, String issueTyp public Object readResolve() { if (jiraUri != null && username != null && password != null) { AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory(); - restClient = factory.createWithBasicHttpAuthentication(jiraUri, username, password.getPlainText()); - restClientExtension = new JiraRestClientExtension( - jiraUri, - new AsynchronousHttpClientFactory() - .createClient( - jiraUri, - new BasicHttpAuthenticationHandler(username, password.getPlainText()))); + if (useBearerAuth) { + BearerAuthenticationHandler handler = new BearerAuthenticationHandler(password.getPlainText()); + restClient = factory.create(jiraUri, handler); + + restClientExtension = new JiraRestClientExtension( + jiraUri, + new AsynchronousHttpClientFactory() + .createClient(jiraUri, new BearerAuthenticationHandler(password.getPlainText()))); + } else { + restClient = factory.createWithBasicHttpAuthentication(jiraUri, username, password.getPlainText()); + restClientExtension = new JiraRestClientExtension( + jiraUri, + new AsynchronousHttpClientFactory() + .createClient( + jiraUri, + new BasicHttpAuthenticationHandler(username, password.getPlainText()))); + } tryCreatingStatusToCategoryMap(); } return this; @@ -575,12 +590,14 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti username = json.getString("username"); password = Secret.fromString(json.getString("password")); + useBearerAuth = json.getBoolean("useBearerAuth"); defaultSummary = json.getString("summary"); defaultDescription = json.getString("description"); if (json.getString("jiraUrl").equals("") || json.getString("username").equals("") || json.getString("password").equals("")) { + useBearerAuth = false; restClient = null; restClientExtension = null; save(); @@ -588,12 +605,23 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti } AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory(); - restClient = factory.createWithBasicHttpAuthentication(jiraUri, username, password.getPlainText()); - restClientExtension = new JiraRestClientExtension( - jiraUri, - new AsynchronousHttpClientFactory() - .createClient( - jiraUri, new BasicHttpAuthenticationHandler(username, password.getPlainText()))); + if (useBearerAuth) { + BearerAuthenticationHandler handler = new BearerAuthenticationHandler(password.getPlainText()); + restClient = factory.create(jiraUri, handler); + + restClientExtension = new JiraRestClientExtension( + jiraUri, + new AsynchronousHttpClientFactory() + .createClient(jiraUri, new BearerAuthenticationHandler(password.getPlainText()))); + } else { + restClient = factory.createWithBasicHttpAuthentication(jiraUri, username, password.getPlainText()); + restClientExtension = new JiraRestClientExtension( + jiraUri, + new AsynchronousHttpClientFactory() + .createClient( + jiraUri, + new BasicHttpAuthenticationHandler(username, password.getPlainText()))); + } tryCreatingStatusToCategoryMap(); save(); return super.configure(req, json); @@ -639,11 +667,15 @@ public TestDataPublisher newInstance(StaplerRequest req, JSONObject json) throws * @param jiraUrl * @param username * @param password + * @param useBearerAuth * @return */ @RequirePOST public FormValidation doValidateGlobal( - @QueryParameter String jiraUrl, @QueryParameter String username, @QueryParameter String password) { + @QueryParameter String jiraUrl, + @QueryParameter String username, + @QueryParameter String password, + @QueryParameter boolean useBearerAuth) { Jenkins.get().checkPermission(Jenkins.ADMINISTER); String serverName; @@ -657,8 +689,14 @@ public FormValidation doValidateGlobal( // JIRA does not offer ways to validate username and password, so we try to query some server // metadata, to see if the configured user is authorized on this server AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory(); - JiraRestClient restClient = - factory.createWithBasicHttpAuthentication(uri, username, pass.getPlainText()); + JiraRestClient restClient; + if (useBearerAuth) { + BearerAuthenticationHandler handler = new BearerAuthenticationHandler(pass.getPlainText()); + restClient = factory.create(uri, handler); + } else { + restClient = factory.createWithBasicHttpAuthentication(uri, username, pass.getPlainText()); + } + MetadataRestClient client = restClient.getMetadataClient(); Promise serverInfoPromise = client.getServerInfo(); ServerInfo serverInfo = serverInfoPromise.claim(); diff --git a/src/main/resources/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher/global.jelly b/src/main/resources/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher/global.jelly index 7f70428..4f05cae 100644 --- a/src/main/resources/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher/global.jelly +++ b/src/main/resources/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher/global.jelly @@ -15,8 +15,13 @@ + + + + + + method="validateGlobal" with="jiraUrl,username,password,useBearerAuth" /> diff --git a/src/main/resources/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher/help-useBearerAuth.html b/src/main/resources/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher/help-useBearerAuth.html new file mode 100644 index 0000000..10b57b5 --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/JiraTestResultReporter/JiraTestDataPublisher/help-useBearerAuth.html @@ -0,0 +1,4 @@ +
+ Uses password data as input for Bearer token, PAT(personal access token) access to enterprise jira (https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html). + Bearer authentication is only supported in Jira Server, for Jira Cloud leave this unchecked +
\ No newline at end of file