maintenance: scope Grafana request authentication (#4288)

This commit is contained in:
Logic
2026-08-03 11:53:10 +08:00
committed by GitHub
parent b1a4f9630e
commit db72f1e402
2 changed files with 90 additions and 4 deletions
@@ -44,7 +44,6 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
@@ -98,7 +97,6 @@ public class ServiceAccountService {
String endpoint = String.format(prefix + CREATE_SERVICE_ACCOUNT_API, url); String endpoint = String.format(prefix + CREATE_SERVICE_ACCOUNT_API, url);
HttpHeaders headers = createHeaders(); HttpHeaders headers = createHeaders();
String body = String.format("{\"name\":\"%s\",\"role\":\"%s\",\"isDisabled\":false}", ACCOUNT_NAME, ACCOUNT_ROLE); String body = String.format("{\"name\":\"%s\",\"role\":\"%s\",\"isDisabled\":false}", ACCOUNT_NAME, ACCOUNT_ROLE);
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(username, password));
HttpEntity<String> request = new HttpEntity<>(body, headers); HttpEntity<String> request = new HttpEntity<>(body, headers);
try { try {
ResponseEntity<String> response = restTemplate.postForEntity(endpoint, request, String.class); ResponseEntity<String> response = restTemplate.postForEntity(endpoint, request, String.class);
@@ -128,7 +126,6 @@ public class ServiceAccountService {
String endpoint = String.format(prefix + CREATE_SERVICE_TOKEN_API, url, accountId); String endpoint = String.format(prefix + CREATE_SERVICE_TOKEN_API, url, accountId);
HttpHeaders headers = createHeaders(); HttpHeaders headers = createHeaders();
String body = String.format("{\"name\":\"%s\"}", CommonUtil.generateRandomWord(6)); String body = String.format("{\"name\":\"%s\"}", CommonUtil.generateRandomWord(6));
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(username, password));
HttpEntity<String> request = new HttpEntity<>(body, headers); HttpEntity<String> request = new HttpEntity<>(body, headers);
try { try {
ResponseEntity<String> response = restTemplate.postForEntity(endpoint, request, String.class); ResponseEntity<String> response = restTemplate.postForEntity(endpoint, request, String.class);
@@ -178,7 +175,6 @@ public class ServiceAccountService {
public ResponseEntity<String> getAccounts() { public ResponseEntity<String> getAccounts() {
String endpoint = String.format(prefix + GET_SERVICE_ACCOUNTS_API, url); String endpoint = String.format(prefix + GET_SERVICE_ACCOUNTS_API, url);
HttpHeaders headers = createHeaders(); HttpHeaders headers = createHeaders();
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(username, password));
HttpEntity<String> request = new HttpEntity<>(headers); HttpEntity<String> request = new HttpEntity<>(headers);
try { try {
ResponseEntity<String> response = restTemplate.exchange(endpoint, HttpMethod.GET, request, String.class); ResponseEntity<String> response = restTemplate.exchange(endpoint, HttpMethod.GET, request, String.class);
@@ -0,0 +1,90 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.hertzbeat.grafana.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.apache.hertzbeat.common.constants.NetworkConstants;
import org.apache.hertzbeat.grafana.config.GrafanaProperties;
import org.apache.hertzbeat.grafana.dao.GrafanaConfigDao;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
/**
* Test case for {@link ServiceAccountService}.
*/
@ExtendWith(MockitoExtension.class)
class ServiceAccountServiceTest {
@Mock
private GrafanaProperties grafanaProperties;
@Mock
private GrafanaConfigDao grafanaConfigDao;
@Mock
private RestTemplate restTemplate;
private ServiceAccountService serviceAccountService;
@BeforeEach
void setUp() {
when(grafanaProperties.getPrefix()).thenReturn("https://");
when(grafanaProperties.getUrl()).thenReturn("grafana.example");
when(grafanaProperties.username()).thenReturn("admin");
when(grafanaProperties.password()).thenReturn("password");
serviceAccountService = new ServiceAccountService(grafanaProperties, grafanaConfigDao, restTemplate);
serviceAccountService.init();
}
@Test
void keepsGrafanaAuthenticationScopedToTheRequest() {
when(restTemplate.exchange(
eq("https://grafana.example/api/serviceaccounts/search"),
eq(HttpMethod.GET),
any(HttpEntity.class),
eq(String.class)))
.thenReturn(ResponseEntity.ok("{\"serviceAccounts\":[]}"));
serviceAccountService.getAccounts();
verify(restTemplate, never()).getInterceptors();
ArgumentCaptor<HttpEntity<String>> requestCaptor = ArgumentCaptor.forClass(HttpEntity.class);
verify(restTemplate).exchange(
eq("https://grafana.example/api/serviceaccounts/search"),
eq(HttpMethod.GET),
requestCaptor.capture(),
eq(String.class));
assertEquals(
"Basic YWRtaW46cGFzc3dvcmQ=",
requestCaptor.getValue().getHeaders().getFirst(NetworkConstants.AUTHORIZATION));
}
}