diff --git a/release-tools/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java b/release-tools/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java index 897318a..02ddcd9 100644 --- a/release-tools/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java @@ -17,6 +17,18 @@ package org.springframework.data.release.issues; import java.util.List; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.AuthCache; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; + import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.cache.CacheManager; @@ -24,7 +36,11 @@ import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.concurrent.ConcurrentMapCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.release.issues.github.GitHubProperties; +import org.springframework.data.release.issues.jira.JiraProperties; import org.springframework.data.release.model.Project; +import org.springframework.data.release.utils.HttpBasicCredentials; +import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.plugin.core.OrderAwarePluginRegistry; @@ -66,15 +82,38 @@ class IssueTrackerConfiguration { return mapper; } + @Bean + HttpComponentsClientHttpRequestFactory clientHttpRequestFactory(JiraProperties jiraProperties, + GitHubProperties gitHubProperties) { + + // Preemptive auth + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + AuthCache authCache = new BasicAuthCache(); + + addPreemptiveAuth(credsProvider, authCache, jiraProperties.getApiUrl(), jiraProperties.getCredentials()); + addPreemptiveAuth(credsProvider, authCache, gitHubProperties.getApiUrl(), gitHubProperties.getHttpCredentials()); + + CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultCredentialsProvider(credsProvider).build(); + + HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); + factory.setHttpContextFactory((httpMethod, uri) -> { + HttpClientContext context = HttpClientContext.create(); + context.setAuthCache(authCache); + return context; + }); + + return factory; + } + @Bean @Qualifier("tracker") - RestTemplateBuilder restTemplate() { + RestTemplateBuilder restTemplate(ClientHttpRequestFactory clientHttpRequestFactory) { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(jacksonObjectMapper()); return new RestTemplateBuilder().messageConverters(converter) - .requestFactory(HttpComponentsClientHttpRequestFactory.class); + .requestFactory(() -> clientHttpRequestFactory); } @Bean @@ -82,6 +121,16 @@ class IssueTrackerConfiguration { return OrderAwarePluginRegistry.of(plugins); } + private static void addPreemptiveAuth(CredentialsProvider credsProvider, AuthCache authCache, String requestUrl, + HttpBasicCredentials credentials) { + HttpHost jiraHost = HttpHost.create(requestUrl); + + credsProvider.setCredentials(new AuthScope(jiraHost), + new UsernamePasswordCredentials(credentials.getUsername(), credentials.getPassword().toString())); + + authCache.put(jiraHost, new BasicScheme()); + } + /** * @author Oliver Gierke */ diff --git a/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHub.java b/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHub.java index 120eda5..e9e4e3d 100644 --- a/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHub.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHub.java @@ -131,7 +131,7 @@ class GitHub implements IssueTracker { try { GitHubIssue gitHubIssue = operations.exchange(ISSUE_BY_ID_URI_TEMPLATE, HttpMethod.GET, - new HttpEntity<>(newUserScopedHttpHeaders()), ISSUE_TYPE, parameters).getBody(); + new HttpEntity<>(new HttpHeaders()), ISSUE_TYPE, parameters).getBody(); tickets.add(toTicket(gitHubIssue)); @@ -219,7 +219,7 @@ class GitHub implements IssueTracker { GithubMilestone githubMilestone = new GithubMilestone(moduleIteration); logger.log(moduleIteration, "Creating GitHub milestone %s", githubMilestone); - HttpHeaders httpHeaders = newUserScopedHttpHeaders(); + HttpHeaders httpHeaders = new HttpHeaders(); Map parameters = newUrlTemplateVariables(); parameters.put("repoName", repositoryName); @@ -265,7 +265,7 @@ class GitHub implements IssueTracker { } private Ticket doCreateTicket(ModuleIteration moduleIteration, String text) { - HttpHeaders httpHeaders = newUserScopedHttpHeaders(); + HttpHeaders httpHeaders = new HttpHeaders(); String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName(); Milestone milestone = getMilestone(moduleIteration, repositoryName); @@ -313,7 +313,7 @@ class GitHub implements IssueTracker { GitHubIssue edit = GitHubIssue.assignedTo(properties.getUsername()); GitHubIssue response = operations.exchange(ISSUE_BY_ID_URI_TEMPLATE, HttpMethod.PATCH, - new HttpEntity<>(edit, newUserScopedHttpHeaders()), ISSUE_TYPE, parameters).getBody(); + new HttpEntity<>(edit, new HttpHeaders()), ISSUE_TYPE, parameters).getBody(); return toTicket(response); } @@ -347,7 +347,7 @@ class GitHub implements IssueTracker { GitHubIssue edit = GitHubIssue.assignedTo(properties.getUsername()).close(); GitHubIssue response = operations.exchange(ISSUE_BY_ID_URI_TEMPLATE, HttpMethod.PATCH, - new HttpEntity<>(edit, newUserScopedHttpHeaders()), ISSUE_TYPE, parameters).getBody(); + new HttpEntity<>(edit, new HttpHeaders()), ISSUE_TYPE, parameters).getBody(); return toTicket(response); } @@ -356,14 +356,6 @@ class GitHub implements IssueTracker { return ticket.getId().startsWith("#") ? ticket.getId().substring(1) : ticket.getId(); } - private HttpHeaders newUserScopedHttpHeaders() { - - HttpHeaders headers = new HttpHeaders(); - headers.set("Authorization", properties.getHttpCredentials().toString()); - - return headers; - } - private Map newUrlTemplateVariables() { Map parameters = new HashMap<>(); @@ -382,7 +374,7 @@ class GitHub implements IssueTracker { logger.log(moduleIteration, "Looking up milestone…"); - doWithPaging(MILESTONE_URI, HttpMethod.GET, parameters, new HttpEntity<>(newUserScopedHttpHeaders()), + doWithPaging(MILESTONE_URI, HttpMethod.GET, parameters, new HttpEntity<>(new HttpHeaders()), MILESTONES_TYPE, milestones -> { Optional milestone = milestones.stream(). // @@ -477,7 +469,7 @@ class GitHub implements IssueTracker { // - mark version as released - HttpHeaders httpHeaders = newUserScopedHttpHeaders(); + HttpHeaders httpHeaders = new HttpHeaders(); GitProject project = GitProject.of(module.getProject()); @@ -530,7 +522,7 @@ class GitHub implements IssueTracker { private Stream getForIssues(String template, Map parameters) { List issues = new ArrayList<>(); - doWithPaging(template, HttpMethod.GET, parameters, new HttpEntity<>(newUserScopedHttpHeaders()), ISSUES_TYPE, + doWithPaging(template, HttpMethod.GET, parameters, new HttpEntity<>(new HttpHeaders()), ISSUES_TYPE, tickets -> { issues.addAll(tickets); return true; diff --git a/release-tools/src/main/java/org/springframework/data/release/issues/jira/Jira.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/Jira.java index 6243f9d..7cf28e7 100644 --- a/release-tools/src/main/java/org/springframework/data/release/issues/jira/Jira.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/Jira.java @@ -173,7 +173,7 @@ class Jira implements JiraConnector { JqlQuery query = JqlQuery .from(trainIteration.stream().filter(moduleIteration -> supports(moduleIteration.getProject()))); - HttpHeaders headers = newUserScopedHttpHeaders(); + HttpHeaders headers = new HttpHeaders(); List tickets = new ArrayList<>(); @@ -227,7 +227,7 @@ class Jira implements JiraConnector { Assert.notNull(moduleIteration, "ModuleIteration must not be null."); Map parameters = newUrlTemplateVariables(); - HttpHeaders httpHeaders = newUserScopedHttpHeaders(); + HttpHeaders httpHeaders = new HttpHeaders(); Optional versionsForModuleIteration = findJiraReleaseVersion(moduleIteration); @@ -257,7 +257,7 @@ class Jira implements JiraConnector { Assert.notNull(module, "ModuleIteration must not be null."); - HttpHeaders httpHeaders = newUserScopedHttpHeaders(); + HttpHeaders httpHeaders = new HttpHeaders(); findJiraReleaseVersion(module) // .filter(JiraReleaseVersion::isActive) // @@ -327,7 +327,7 @@ class Jira implements JiraConnector { private Ticket doCreateTicket(ModuleIteration moduleIteration, String text) { - HttpHeaders httpHeaders = newUserScopedHttpHeaders(); + HttpHeaders httpHeaders = new HttpHeaders(); Map parameters = newUrlTemplateVariables(); findJiraReleaseVersion(moduleIteration).orElseThrow( @@ -354,7 +354,7 @@ class Jira implements JiraConnector { Assert.notNull(ticket, "Ticket must not be null."); - HttpHeaders httpHeaders = newUserScopedHttpHeaders(); + HttpHeaders httpHeaders = new HttpHeaders(); Map parameters = newUrlTemplateVariables(); parameters.put("ticketId", ticket.getId()); @@ -408,7 +408,7 @@ class Jira implements JiraConnector { Assert.notNull(ticket, "Ticket must not be null."); - HttpHeaders httpHeaders = newUserScopedHttpHeaders(); + HttpHeaders httpHeaders = new HttpHeaders(); Map parameters = newUrlTemplateVariables(); parameters.put("ticketId", ticket.getId()); @@ -437,7 +437,7 @@ class Jira implements JiraConnector { Assert.notNull(ticket, "Ticket must not be null."); - HttpHeaders httpHeaders = newUserScopedHttpHeaders(); + HttpHeaders httpHeaders = new HttpHeaders(); Map parameters = newUrlTemplateVariables(); parameters.put("ticketId", ticket.getId()); @@ -521,7 +521,7 @@ class Jira implements JiraConnector { // - mark version as releases - HttpHeaders httpHeaders = newUserScopedHttpHeaders(); + HttpHeaders httpHeaders = new HttpHeaders(); findJiraReleaseVersion(module) // .filter(JiraReleaseVersion::isOpen) // @@ -709,18 +709,6 @@ class Jira implements JiraConnector { String.format("%s/browse/%s", jiraProperties.getApiUrl(), issue.getKey()), jiraTicketStatus); } - /** - * Returns new {@link HttpHeaders} with authentication headers. - * - * @return - */ - private HttpHeaders newUserScopedHttpHeaders() { - - HttpHeaders headers = new HttpHeaders(); - headers.set("Authorization", jiraProperties.getCredentials().toString()); - return headers; - } - private Map newUrlTemplateVariables() { Map parameters = new HashMap<>(); return parameters; diff --git a/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraProperties.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraProperties.java index 49a6b9f..1e76251 100644 --- a/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraProperties.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraProperties.java @@ -36,7 +36,7 @@ import org.springframework.util.Assert; @Data @Component @ConfigurationProperties(prefix = "jira") -class JiraProperties { +public class JiraProperties { private @Getter(AccessLevel.PRIVATE) Password password; private String username, apiUrl;