





→ Instance의 Project Id를 통해서 Instance가 현재 속해있는 Project의 정보를 받아오도록 구현할 예정이다.
- Java version: 11
- Spring Framework version: 2.7.16
package openstack.prometheus.libvirt;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.net.URISyntaxException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@RestController
@Slf4j
public class PrometheusDataFetcher {
private final RestTemplate restTemplate;
@Autowired
public PrometheusDataFetcher(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
@GetMapping("/prometheus-metrics")
public ResponseEntity<String> getPrometheusMetrics() throws URISyntaxException {
// Prometheus 메트릭 데이터를 가져올 URL 설정
String prometheusMetricsURL = "http://133.186.215.103:9000/metrics";
// RestTemplate을 사용하여 메트릭 데이터를 문자열로 가져오기
ResponseEntity<String> response = restTemplate.getForEntity(prometheusMetricsURL, String.class);
String metricData = response.getBody();
// 정규 표현식 패턴
Pattern pattern = Pattern.compile("instanceName=\"([^\"]+)\".*projectId=\"([^\"]+)\"");
Matcher matcher = pattern.matcher(metricData);
StringBuilder result = new StringBuilder();
while (matcher.find()) {
String instanceName = matcher.group(1);
String projectId = matcher.group(2);
result.append("Instance Name: ").append(instanceName).append("\n");
result.append("Project Id: ").append(projectId).append("\n");
}
return ResponseEntity.ok(result.toString());
}
}

package openstack.prometheus.libvirt;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
@Component
@Slf4j
public class Token {
private final RestTemplate restTemplate;
// RestTemplate을 초기화하기 위한 생성자
@Autowired
public Token(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
// OpenStack Identity 기본 설정 값을 초기화
this.username = "admin";
this.password = "20secret23";
this.authUrl = "http://133.186.215.103/identity/v3/auth/tokens";
}
private String authUrl;
private String username;
private String password;
public String fetchToken() throws URISyntaxException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 인증을 위한 JSON 요청 생성
String jsonRequest = "{\"auth\": {\"identity\": {\"methods\": [\"password\"],\"password\": {\"user\": {\"name\": \"" + username + "\",\"domain\": {\"id\": \"default\"},\"password\": \"" + password + "\"}},\"scope\": {\"domain\": {\"id\": \"default\"}}}}}";
// JSON 요청, 헤더, HTTP 메서드로 RequestEntity 생성
RequestEntity<String> requestEntity = new RequestEntity<>(jsonRequest, headers, HttpMethod.POST, new URI(authUrl));
// 인증 요청을 보내고 응답을 받음
ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
// 응답에서 헤더 정보를 추출
HttpHeaders responseHeaders = responseEntity.getHeaders();
log.info(responseHeaders.toString());
// 응답 헤더에서 X-Subject-Token (인증 토큰) 추출
List<String> tokenList = responseHeaders.get("X-Subject-Token");
// 성공 로그를 기록하고 인증 토큰 반환
log.info("인증 성공");
return tokenList.get(0);
}
}


- Issue: 토큰 값이 정상적으로 파싱되어 확인할 수 있었지만, http://localhost:8080/prometheus-metrics 로 요청을 보내면 401 Unauthorized에 의해서 사이트 접속이 차단 되었다.
- 하지만 받아온 토큰 값을 이용해서 Openstack 커널에서 Openstack API를 통해 요청을 하면 아래와 같이 정상적으로 값이 받아와졌다.
- 문제점은 http://localhost:8080/prometheus-metrics 요청할 때, 헤더에 토큰 값을 넣어주지 않았다.
인증 & 인가를 위해서 필수적으로 헤더에 해당 정보를 포함해줘야하는 것을 알고있었는데 security, jwt를 사용안한지 오래되어 까맣게 잊고 있었다.
CS공부를 더 열심히 해야겠다.
아래는 수정된 코드이다.
→ GET 요청을 보낼 때 헤더에 받아온 Token을 set
헤더를 수정하기 위해 getForEntity가 아닌, restTemplate의 exchange 메소드를 사용하였다.- 결과