diff --git a/.gitignore b/.gitignore index c507849..290f8e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target .idea +app.log \ No newline at end of file diff --git a/actuator-demo.iml b/actuator-demo.iml new file mode 100644 index 0000000..cdf5921 --- /dev/null +++ b/actuator-demo.iml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/k8s.yaml b/k8s.yaml index c0c1707..9cc493a 100644 --- a/k8s.yaml +++ b/k8s.yaml @@ -37,7 +37,7 @@ metadata: app: jenkins-backend-demo annotations: prometheus.io/scrape: 'true' - #prometheus.io/path: '/metrics' + prometheus.io/path: '/actuator/prometheus' #'/metrics' prometheus.io/port: '30011' #'30011' spec: selector: diff --git a/pom.xml b/pom.xml index 27b163e..f72f1df 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 2.0.0.RELEASE + 2.2.1.RELEASE @@ -25,7 +25,16 @@ - + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot spring-boot-starter-web @@ -58,6 +67,16 @@ simpleclient_pushgateway 0.9.0 + + + io.micrometer + micrometer-registry-prometheus + + + org.springframework.security + spring-security-test + test + diff --git a/spring-boot-docker.iml b/spring-boot-docker.iml index 5e143f0..890db68 100644 --- a/spring-boot-docker.iml +++ b/spring-boot-docker.iml @@ -25,66 +25,91 @@ - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + - - - - + + + + + + - - - - - - + + + + - + + + + + \ No newline at end of file diff --git a/src/main/java/com/neo/config/ActuatorSecurityConfig.java b/src/main/java/com/neo/config/ActuatorSecurityConfig.java new file mode 100644 index 0000000..fbbd609 --- /dev/null +++ b/src/main/java/com/neo/config/ActuatorSecurityConfig.java @@ -0,0 +1,43 @@ +package com.neo.config; + + +import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; +import org.springframework.boot.actuate.context.ShutdownEndpoint; +import org.springframework.boot.autoconfigure.security.servlet.PathRequest; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter { + + /* + This spring security configuration does the following + + 1. Restrict access to the Shutdown endpoint to the ACTUATOR_ADMIN role. + 2. Allow access to all other actuator endpoints. + 3. Allow access to static resources. + 4. Allow access to the home page (/). + 5. All other requests need to be authenticated. + 5. Enable http basic authentication to make the configuration complete. + You are free to use any other form of authentication. + */ + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .requestMatchers(EndpointRequest.to(ShutdownEndpoint.class)) + .hasRole("ACTUATOR_ADMIN") + .requestMatchers(EndpointRequest.toAnyEndpoint()) + .permitAll() + .requestMatchers(PathRequest.toStaticResources().atCommonLocations()) + .permitAll() + .antMatchers("/", "/slowApi") + .permitAll() + .antMatchers("/**") + .authenticated() + .and() + .httpBasic(); + } +} diff --git a/src/main/java/com/neo/controller/DockerController.java b/src/main/java/com/neo/controller/DockerController.java index 820b010..034ece3 100644 --- a/src/main/java/com/neo/controller/DockerController.java +++ b/src/main/java/com/neo/controller/DockerController.java @@ -2,7 +2,12 @@ package com.neo.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; import io.prometheus.client.Counter; +import java.util.Random; +import java.util.concurrent.TimeUnit; + @RestController @@ -12,11 +17,11 @@ public class DockerController { // .name("requests_total").help("Total requests.").register(); static final Counter requests = Counter.build() - .name("my_library_requests_total").help("Total requests.") + .name("test_backend_requests_total").help("Total requests.") .labelNames("method").register(); - @RequestMapping("/") + @RequestMapping("/hello") public String index() { // Counter // requests.inc(); @@ -25,4 +30,22 @@ public class DockerController { return "Hello Docker! "; } + + + @GetMapping("/") + public String sayHello(@RequestParam(value = "name", defaultValue = "Guest") String name) { + return "Hello " + name + "!!"; + } + + @GetMapping("/slowApi") + public String timeConsumingAPI(@RequestParam(value = "delay", defaultValue = "0") Integer delay) throws InterruptedException { + if(delay == 0) { + Random random = new Random(); + delay = random.nextInt(10); + } + + TimeUnit.SECONDS.sleep(delay); + return "Result"; + } + } diff --git a/src/main/java/com/neo/health/CustomHealthIndicator.java b/src/main/java/com/neo/health/CustomHealthIndicator.java new file mode 100644 index 0000000..81911b3 --- /dev/null +++ b/src/main/java/com/neo/health/CustomHealthIndicator.java @@ -0,0 +1,19 @@ +package com.neo.health; + +import org.springframework.boot.actuate.health.AbstractHealthIndicator; +import org.springframework.boot.actuate.health.Health; +import org.springframework.stereotype.Component; + +@Component +public class CustomHealthIndicator extends AbstractHealthIndicator { + + @Override + protected void doHealthCheck(Health.Builder builder) throws Exception { + // Use the builder to build the health status details that should be reported. + // If you throw an exception, the status will be DOWN with the exception message. + + builder.up() + .withDetail("app", "Alive and Kicking") + .withDetail("error", "Nothing! I'm good."); + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e69de29..59bca2b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -0,0 +1,23 @@ +# Logging +logging.file=app.log + +# Spring Security default user name and password +spring.security.user.name=actuator +spring.security.user.password=actuator +spring.security.user.roles=ACTUATOR_ADMIN + +# INFO ENDPOINT CONFIGURATION +info.app.name=@project.name@ +info.app.description=@project.description@ +info.app.version=@project.version@ +info.app.encoding=@project.build.sourceEncoding@ +info.app.java.version=@java.version@ + +# SHUTDOWN ENDPOINT (ShutdownEndpoint) +management.endpoint.shutdown.enabled=true + +# HEALTH ENDPOINT +management.endpoint.health.show-details=always + +# ENDPOINTS WEB CONFIGURATION +management.endpoints.web.exposure.include=* \ No newline at end of file diff --git a/src/main/resources/prometheus.yml b/src/main/resources/prometheus.yml new file mode 100644 index 0000000..2e82c40 --- /dev/null +++ b/src/main/resources/prometheus.yml @@ -0,0 +1,28 @@ +# my global config +global: + scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. + evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. + # scrape_timeout is set to the global default (10s). + +# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. +rule_files: + # - "first_rules.yml" + # - "second_rules.yml" + +# A scrape configuration containing exactly one endpoint to scrape: +# Here it's Prometheus itself. +scrape_configs: + # The job name is added as a label `job=` to any timeseries scraped from this config. + - job_name: 'prometheus' + + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + static_configs: + - targets: ['127.0.0.1:9090'] + + - job_name: 'spring-actuator' + metrics_path: '/actuator/prometheus' + scrape_interval: 5s + static_configs: + - targets: ['HOST_IP:8080']