diff --git a/.github/workflows/SonarQube.yaml b/.github/workflows/SonarQube.yaml
deleted file mode 100644
index 16dd20d..0000000
--- a/.github/workflows/SonarQube.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-name: SonarCloud scan for User Services (Test Stage)
-on:
- workflow_call:
- secrets:
- SONAR_TOKEN:
- required: true
-jobs:
- sonar-cloud-scan:
- name: Build and analyze
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- with:
- fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- - name: Set up JDK 17
- uses: actions/setup-java@v3
- with:
- java-version: 17
- distribution: 'zulu' # Alternative distribution options are available.
- - name: Cache SonarCloud packages
- uses: actions/cache@v3
- with:
- path: ~/.sonar/cache
- key: ${{ runner.os }}-sonar
- restore-keys: ${{ runner.os }}-sonar
- - name: Cache Maven packages
- uses: actions/cache@v3
- with:
- path: ~/.m2
- key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
- restore-keys: ${{ runner.os }}-m2
- - name: Build and analyze
- env:
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=DevOps-Video-Sharing_UserService
\ No newline at end of file
diff --git a/.github/workflows/build-image.yaml b/.github/workflows/build-image.yaml
new file mode 100644
index 0000000..9fd2079
--- /dev/null
+++ b/.github/workflows/build-image.yaml
@@ -0,0 +1,37 @@
+name: Build Image User Service
+
+on:
+ workflow_call:
+ secrets:
+ DOCKER_HUB_ACCESS_TOKEN:
+ required: true
+
+jobs:
+ build-image:
+ name: Build and Push Docker Image
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Setup JDK 17
+ uses: actions/setup-java@v3
+ with:
+ distribution: 'corretto'
+ java-version: 17
+
+ - name: Login to Docker Hub
+ uses: docker/login-action@v2
+ with:
+ username: datuits
+ password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
+
+ - name: Build the application
+ run: |
+ mvn clean
+ mvn -B package --file pom.xml
+
+ - name: Build and Push the docker image
+ run: |
+ docker build -t datuits/devops-user-service:latest .
+ docker push datuits/devops-user-service:latest
\ No newline at end of file
diff --git a/.github/workflows/deploymentCD.yaml b/.github/workflows/deploymentCD.yaml
new file mode 100644
index 0000000..3dac504
--- /dev/null
+++ b/.github/workflows/deploymentCD.yaml
@@ -0,0 +1,58 @@
+name: Continuous Deployment for User Service
+
+on:
+ workflow_run:
+ workflows: ["Continuous Integration for Comment Service"]
+ types:
+ - completed
+
+env:
+ PROJECT_ID: gke-project-423206
+ CLUSTER_NAME: autopilot-cluster-1
+ ZONE: us-central1
+
+jobs:
+ deploy:
+ name: Deploy to GKE Autopilot
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Setup JDK 17
+ uses: actions/setup-java@v3
+ with:
+ distribution: 'corretto'
+ java-version: 17
+
+ - name: Build the application
+ run: |
+ mvn clean
+ mvn -B package --file pom.xml
+
+ - name: Authenticate
+ uses: google-github-actions/auth@v2
+ with:
+ credentials_json: ${{ secrets.GCP_SA_KEY }}
+
+ - name: Configure gcloud
+ uses: google-github-actions/setup-gcloud@v2
+ with:
+ project_id: ${{ env.PROJECT_ID }}
+ install_components: 'gke-gcloud-auth-plugin'
+
+ - name: Set cluster context
+ run: |
+ gcloud container clusters get-credentials ${{ env.CLUSTER_NAME }} --zone ${{ env.ZONE }} --project ${{ env.PROJECT_ID }}
+
+ - name: Apply Kubernetes manifests
+ run: |
+ kubectl apply -f resources.yaml
+
+ notifications:
+ needs: deploy
+ uses: ./.github/workflows/notifyCD.yaml
+ secrets:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL}}
+
+###Demo###
\ No newline at end of file
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index e7812f3..e824872 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -1,13 +1,13 @@
-name: Test Stage for Comment Service
+name: Dev Stage for User Service
on:
push:
branches:
- - test
+ - dev
jobs:
testing:
- name: Testing Comment Service
+ name: Testing User Service
runs-on: ubuntu-latest
steps:
@@ -26,18 +26,15 @@ jobs:
- name: Unit Tests
run: mvn -B test --file pom.xml
- sonar-cloud-scan:
+ build-image:
needs: testing
- uses: ./.github/workflows/SonarQube.yaml
+ uses: ./.github/workflows/build-image.yaml
secrets:
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
-
- scan-image:
- needs: sonar-cloud-scan
- uses: ./.github/workflows/scan-image.yaml
-
- notify:
- needs: scan-image
- uses: ./.github/workflows/notifyCI.yaml
- secrets:
- SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
+
+ # notify:
+ # needs: build-image
+ # uses: ./.github/workflows/notifyCI.yaml
+ # secrets:
+ # SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+###Testing Build###
diff --git a/.github/workflows/notifyCD.yaml b/.github/workflows/notifyCD.yaml
new file mode 100644
index 0000000..20f2b28
--- /dev/null
+++ b/.github/workflows/notifyCD.yaml
@@ -0,0 +1,36 @@
+name: Send Slack Notification for User Service
+
+on:
+ workflow_call:
+ secrets:
+ SLACK_WEBHOOK_URL:
+ required: true
+
+jobs:
+ success_notifier:
+ if: success()
+ runs-on: ubuntu-latest
+ steps:
+ - name: Send success notification on Slack
+ uses: slackapi/slack-github-action@v1.24.0
+ with:
+ payload: |
+ {
+ "text": "The Continuous Deployment for User Service workflow has completed successfully."
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+
+ failure_notifier:
+ if: failure()
+ runs-on: ubuntu-latest
+ steps:
+ - name: Send failure notification on Slack
+ uses: slackapi/slack-github-action@v1.24.0
+ with:
+ payload: |
+ {
+ "text": "The Continuous Deployment for User Service workflow has failed."
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
\ No newline at end of file
diff --git a/.github/workflows/notifyCI.yaml b/.github/workflows/notifyCI.yaml
index 2dc3428..2b7db47 100644
--- a/.github/workflows/notifyCI.yaml
+++ b/.github/workflows/notifyCI.yaml
@@ -1,4 +1,4 @@
-name: Send Slack Notification for User Service (Test Stage)
+name: Send Slack Notification for User Service
on:
workflow_call:
diff --git a/.github/workflows/scan-image.yaml b/.github/workflows/scan-image.yaml
deleted file mode 100644
index d366468..0000000
--- a/.github/workflows/scan-image.yaml
+++ /dev/null
@@ -1,47 +0,0 @@
-name: Scan Image User Service (Test Stage)
-on:
- workflow_call:
-
-jobs:
- scan-image:
- name: Security Scan
- runs-on: ubuntu-latest
- steps:
- - name: Install Trivy
- run: |
- sudo apt-get update
- sudo apt-get install -y wget
- wget https://github.com/aquasecurity/trivy/releases/download/v0.40.0/trivy_0.40.0_Linux-64bit.deb
- sudo dpkg -i trivy_0.40.0_Linux-64bit.deb
-
- - name: Scan Docker image with Trivy
- id: scan-image
- run: |
- trivy image --format json --output scan-results.json datuits/devops-user-service:latest
-
- - name: Extract high and critical vulnerabilities
- id: extract_vulnerabilities
- run: |
- jq -r '
- def hr(severity):
- if severity == "HIGH" or severity == "CRITICAL" then true else false end;
- def to_md:
- "| " + (.VulnerabilityID // "") + " | " + (.PkgName // "") + " | " + (.InstalledVersion // "") + " | " + (.Severity // "") + " | " + (.Title // "") + " |";
- [
- "# Docker Image Scan Results",
- "",
- "## High and Critical Vulnerabilities",
- "",
- "| Vulnerability ID | Package | Version | Severity | Description |",
- "|------------------|---------|---------|----------|-------------|",
- (.Results[] | .Vulnerabilities[] | select(hr(.Severity)) | to_md),
- ""
- ] | join("\n")
- ' scan-results.json > vulnerability-report.md
-
- - name: Upload vulnerability report
- uses: actions/upload-artifact@v2
- with:
- name: vulnerability-report
- path: vulnerability-report.md
-
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index c90ca06..c450841 100644
--- a/pom.xml
+++ b/pom.xml
@@ -83,7 +83,11 @@
2.10.1
-
+
+ net.logstash.logback
+ logstash-logback-encoder
+ 7.0.1
+
diff --git a/src/main/java/com/programming/userService/controller/UserController.java b/src/main/java/com/programming/userService/controller/UserController.java
index 3ccf6d0..054993f 100644
--- a/src/main/java/com/programming/userService/controller/UserController.java
+++ b/src/main/java/com/programming/userService/controller/UserController.java
@@ -33,17 +33,27 @@
import java.util.Map;
import java.util.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
@RestController
@AllArgsConstructor
@RequestMapping("/user")
public class UserController {
+ private static final Logger logger = LoggerFactory.getLogger(UserController.class);
+
@GetMapping("/")
public String getServiceName(){
+ //ELK
+ MDC.put("type", "userservice");
+ logger.info("User Service Start");
return "User Service";
}
- private final AuthUserRepository userRepository;
+
+
+ private final AuthUserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@Autowired
private JavaMailSender javaMailSender;
@@ -87,6 +97,11 @@ public ResponseEntity registerUser(@RequestBody AuthUser user) {
user.setTimestamp(new Date());
user.setAvatar(getDefaultAvatar());
AuthUser save = userRepository.save(user);
+ AuthUser userFromDb = userRepository.findByUsername(user.getUsername())
+ .orElseThrow(() -> new Exception("User not found"));
+ MDC.put("type", "userservice");
+ MDC.put("action", "register");
+ logger.info("UserID: " + userFromDb.getId());
return ResponseEntity.ok(save);
} catch (Exception e) {
return ResponseEntity.internalServerError().body(e.getMessage());
@@ -106,6 +121,9 @@ public ResponseEntity loginUser(@RequestBody AuthUser user) {
AuthUser userFromDb = userRepository.findByUsername(user.getUsername())
.orElseThrow(() -> new Exception("User not found"));
if (passwordEncoder.matches(user.getPassword(), userFromDb.getPassword())) {
+ MDC.put("type", "userservice");
+ MDC.put("action", "login");
+ logger.info("UserID: " + userFromDb.getId());
return ResponseEntity.ok(userFromDb);
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid credentials");
@@ -163,6 +181,9 @@ public ResponseEntity updateProfile(@PathVariable("id") String id, @RequestBody
userFromDb.setFirstName(user.getFirstName());
userFromDb.setLastName(user.getLastName());
AuthUser save = userRepository.save(userFromDb);
+ MDC.put("type", "userservice");
+ MDC.put("action", "update-profile");
+ logger.info("UserID: " + userFromDb.getId());
return ResponseEntity.ok(HttpStatus.OK);
} catch (Exception e) {
@@ -184,7 +205,9 @@ public ResponseEntity changePassword(@PathVariable("id") String id,
userFromDb.setPassword(passwordEncoder.encode(changePasswordRequest.getNewPassword()));
AuthUser save = userRepository.save(userFromDb);
-
+ MDC.put("type", "userservice");
+ MDC.put("action", "change-password");
+ logger.info("UserID: " + userFromDb.getId());
return ResponseEntity.ok("Password changed successfully");
} catch (Exception e) {
return ResponseEntity.internalServerError().body(e.getMessage());
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 091832f..d9a056f 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -18,3 +18,6 @@ spring.mail.username=21520714@gm.uit.edu.vn
spring.mail.password=vkux umrv rtkd svsy
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
+
+# logstash
+logging.config=classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000..6b0ebf7
--- /dev/null
+++ b/src/main/resources/logback-spring.xml
@@ -0,0 +1,11 @@
+
+
+ 192.168.120.213:5050
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/TestUserService.java b/src/test/java/TestUserService.java
index edff7ed..042a686 100644
--- a/src/test/java/TestUserService.java
+++ b/src/test/java/TestUserService.java
@@ -17,3 +17,4 @@ public void testGetServiceName() throws Exception {
.andExpect(status().isOk());
}
}
+/////