diff --git a/.github/workflows/firebase-hosting-merge.yml b/.github/workflows/firebase-hosting-merge.yml deleted file mode 100644 index 08d3026f..00000000 --- a/.github/workflows/firebase-hosting-merge.yml +++ /dev/null @@ -1,23 +0,0 @@ -# This file was auto-generated by the Firebase CLI -# https://github.com/firebase/firebase-tools - -name: Deploy to Firebase Hosting on merge -'on': - push: - branches: - - main -jobs: - build_and_deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - run: npm ci && npm run build - env: - VITE_APP_API_ENDPOINT_URL: '${{ secrets.VITE_APP_API_ENDPOINT_URL }}' - VITE_APP_TMDB_V3_API_KEY: '${{ secrets.VITE_APP_TMDB_V3_API_KEY }}' - - uses: FirebaseExtended/action-hosting-deploy@v0 - with: - repoToken: '${{ secrets.GITHUB_TOKEN }}' - firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_WEBSITES_F0426 }}' - channelId: live - projectId: websites-f0426 diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml deleted file mode 100644 index a56481bc..00000000 --- a/.github/workflows/firebase-hosting-pull-request.yml +++ /dev/null @@ -1,17 +0,0 @@ -# This file was auto-generated by the Firebase CLI -# https://github.com/firebase/firebase-tools - -name: Deploy to Firebase Hosting on PR -'on': pull_request -jobs: - build_and_preview: - if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - run: npm ci && npm run build - - uses: FirebaseExtended/action-hosting-deploy@v0 - with: - repoToken: '${{ secrets.GITHUB_TOKEN }}' - firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_WEBSITES_F0426 }}' - projectId: websites-f0426 diff --git a/.gitignore b/.gitignore index f1887470..14b10131 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,5 @@ .env.production.local npm-debug.log* -yarn.lock yarn-debug.log* yarn-error.log* diff --git a/Dockerfile b/Dockerfile index e8455afe..5e81b022 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16.17.0-alpine as builder +FROM node:16.17.0-alpine AS builder WORKDIR /app COPY ./package.json . COPY ./yarn.lock . diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..8d3187af --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,133 @@ +pipeline { + agent any + + tools { + nodejs 'NodeJS' + } + + environment { + SONARQUBE_SCANNER = tool 'Sonar' + DOCKER_CREDENTIALS = credentials('Docker') + TMDB_CREDENTIALS = credentials('tmdb') + } + + stages { + stage('Clean Workspace') { + steps { + echo "Cleaning Workspace..." + cleanWs() + echo 'Workspace cleaned.' + } + } + + stage('Clone GitHub Repository') { + steps { + script { + echo 'Cloning GitHub repository...' + git branch: 'main', url: 'https://github.com/Abdullah-0-3/NetflixCloneK8s.git' + } + echo 'Cloning done.' + } + } + + stage('SonarQube Quality Analysis') { + steps { + script { + withSonarQubeEnv('Sonar') { + echo 'SonarQube scanner environment configured.' + sh "${SONARQUBE_SCANNER}/bin/sonar-scanner -Dsonar.projectName=NetflixClone -Dsonar.projectKey=NetflixClone" + } + } + echo 'SonarQube analysis started.' + } + } + + stage('Install Dependencies') { + steps { + script { + sh 'npm install' + echo 'Dependencies installed.' + } + } + } + + stage('OWASP Dependency Check') { + steps { + script { + dependencyCheck additionalArguments: '--scan', odcInstallation: 'dc' + dependencyCheckPublisher pattern: '**/dependency-check-report.xml' + echo 'OWASP Dependency Check completed.' + } + } + } + + stage('SonarQube Gate Analysis') { + steps { + script { + echo 'Waiting for SonarQube gate analysis...' + timeout(time: 2, unit: 'MINUTES'){ + waitForQualityGate abortPipeline: false + } + + } + } + } + + stage('Trivy File System Scan') { + steps { + script { + sh 'trivy fs --quiet --ignore-unfixed --format json . > trivy-fs-scan.txt' + echo 'Trivy file system scan completed.' + } + } + } + + stage('Build Docker Image') { + steps { + script { + def imageName = "muhammadabdullahabrar/devops:netflix-clone" + sh "docker build --build-arg TMDB_V3_API_KEY=${TMDB_CREDENTIALS} -t ${imageName} ." + echo 'Docker image built.' + } + } + } + + stage('Trivy Image Scan') { + steps { + script { + def imageName = "muhammadabdullahabrar/devops:netflix-clone" + sh "trivy image --quiet --ignore-unfixed --format json ${imageName} > trivy-image-scan.txt" + echo 'Trivy image scan completed.' + } + } + } + + stage('Push Image to Docker Hub') { + steps { + withCredentials([usernamePassword(credentialsId: 'Docker', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) { + script { + def imageName = "muhammadabdullahabrar/devops:netflix-clone" + sh """ + set -x + echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin + docker push ${imageName} + docker logout + """ + } + } + } + } + + stage('Send Email with Attachments') { + steps { + emailext( + attachLog: true, + subject: "Netflix Clone Pipeline - Jenkins", + body: """Project: ${env.JOB_NAME} - ${env.BUILD_NUMBER} has been built successfully. Check console output at ${env.BUILD_URL}.""", + to: 'abdullahabrar4843@gmail.com', // Change mail here + attachmentsPattern: 'trivy-fs-scan.txt,trivy-image-scan.txt,dependency-check-report.xml' + ) + } + } + } +} \ No newline at end of file diff --git a/Netflix Clone Deployment - DevSecOps Project.pdf b/Netflix Clone Deployment - DevSecOps Project.pdf new file mode 100644 index 00000000..1d9958b4 Binary files /dev/null and b/Netflix Clone Deployment - DevSecOps Project.pdf differ diff --git a/README.md b/README.md index 25693bed..efde81f8 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,305 @@ -
- -
- Home Page
-
- Mini Portal
-
- Detail Modal
-
- Grid Genre Page
-
- Watch Page with customer contol bar
-
+
+I got this code from [Github Netflix Clone](https://github.com/jason-liu22/netflix-clone-react-typescript). He did a great job. I just forked it and added:
+
+1. Improved Dockerfile
+2. Resolved Yarn Lock Issues
+3. Added Jenkinfile
+4. Added Kubernetes Manifets
+
+I am doing this **DevSecOps Project** for better understand of different softwares using differnet new and modern techniques. If you want to colloborate then you can visit my
+
+- [LinkedIn](https://www.linkedin.com/in/muhammadabdullahabrar)
+- [Github](https://www.github.com/Abdullah-0-3)
+- **Email:** abdullahabrar4843@gmail.com
+- **Phone Number:** +(92) 3095306826
+
+I hope if you try this project you will get a better understanding of projects and using new techniques like Grafana and Prometheus.
+
+---
+### Tools Used
+
+- Jenkins
+- Docker
+- Kuberentes
+- ArgoCD
+- OWASP
+- SonarCube
+- Trivy
+- Prometheus
+- Grafana
+
+---
+### DevSecOps Project Architecture
+
+
+
+From Netflix Code to Github. Github to Jenkins and using OWASP, SonaryCube and Trivy to check Dependencies and and Pushing made images to Dockerhub.
+
+Using Dockerhub image to use for K8s using from ArgoCD. After that integreating it to Prometheus and using Grafana Dashboards to view the Analytics
+
+---
+### Overview of Neflix Clone
+
+
+
+
+
+---
+### Prerequisite
+
+1. Clone the Repository
+ ```
+ git clone https://github.com/Abdullah-0-3/NetflixCloneTypescript.git
+ ```
+2. Install [Docker](#docker-installation)
+3. Install Dependencies
+ You should be in the place where you cloned the repo
+ ```
+ cd downloads
+ chmod +x install_kubectl.sh
+ chmod +x install_kind.sh
+ chmod +x install_helm.sh
+ ```
+ After this process run the scripts
+ ```
+ sudo ./install_kubectl.sh
+ sudo ./install_kind.sh
+ sudo ./install_helm.sh
+ ```
+ Checking if it runs
+ ```
+ kubectl version --client
+ kind version
+ kind create cluster --config kind-config.yml
+ kubectl get nodes
+ ```
+ If did not work then check if **Docker** is installed.
+
+4. Go to [TMDB](https://www.themoviedb.org/).
+ - Rgister an Account
+ - Log into you Account
+ - Go to Settings
+ - Genereate and API by filling all the requirements for the API Key
+ - Copy and Store it in a safe spot.
+5. Check if you are ready to go by checking if Kuberentes Nodes are Ready, Linux is set and make sure you update it
+
+> (Recomendation) Make sure you give your machine 8GB Ram and 15GB Hard Disk.
+
+---
+### Docker Installation
+1. Update System
+ ```
+ sudo dnf update -y
+ ```
+2. Install Packages
+ ```
+ sudo dnf install -y dnf-utils
+ sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
+ ```
+3. Download Docker
+ ```
+ sudo dnf install -y docker-ce docker-ce-cli containerd.io
+ docker --version
+ ```
+4. Start Docker
+ ```
+ sudo systemctl start docker
+ sudo systemctl enable docker
+ ```
+5. Give Permissions
+ ```
+ sudo usermod -aG docker $USER
+ ```
+
+---
+### Jenkins Setup
+
+1. Install Java
+ ```
+ sudo dnf update -y
+ sudo dnf install fontconfig java-17-openjdk -y
+ java --version
+ ```
+2. Get Go with Jenkins
+ ```
+ sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
+ sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
+ sudo dnf install jenkins -y
+ ```
+3. Start Jenkins
+ ```
+ sudo systemctl start jenkins
+ sudo systemctl status jenkins
+ ```
+ It runs on port 8080
+
+4. Open Ports
+ If you are using AWS Instance Security Bind your ports
+ ```
+ sudo firewall-cmd --permanent --add-port=8080/tcp --zone=public
+ sudo firewall-cmd --reload
+ ```
+5. You can use jenkins is your Browser
+ ```
+ sudo usermod -aG docker jenkins
+ ```
+6. Create a Pipeline and use it for further configuration
+7. Setup your Jenkins Pipeline for that you need to learn Jenkins
+
+> Jenkins Downloads
+- SonarQube Scanner
+- SonarQube Quality Gates
+- NodeJS
+- Docker
+- Pipeline Stage View
+- OWASP Dependecy Check
+
+> Jenkins Credentials
+- Email Credentials
+- Docker Credentials
+- TMDB Secret File
+- SonarQube Administrator Token
+
+---
+### SonarCube Setup
+1. Start Docker
+ ```
+ sudo systemctl start docker
+ ```
+2. Pull SonarCube image
+ ```
+ docker pull sonarqube:lts-community
+ ```
+3. Run SonarCube
+ ```
+ docker run --name sonarqube -d -p 9000:9000 sonarqube:lts-community
+ ```
+4. Allow Firewall
+ ```
+ sudo firewall-cmd --permanent --zone=public --add-port=9000/tcp
+ sudo firewall-cmd --reload
+ ```
+5. Ready to GO!
+
+> Create a WebHook
+> Apply Admin Token in Jenkins
+
+---
+### Trivy Setup
+1. Update System
+ ```
+ sudo dnf update -y
+ ```
+2. Import Packages
+ ```
+ sudo vim /etc/yum.repos.d/trivy.repo
+ ```
+ Paste it there
+ ```
+ [trivy]
+ name=Trivy repository
+ baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$releasever/$basearch/
+ gpgcheck=0
+ enabled=1
+ ```
+3. Download Trviy
+ ```
+ sudo dnf -y update
+ sudo dnf -y install trivy
+ ```
+4. Check Trivy Version
+ ```
+ trivy --version
+ ```
+5. Done!!!!
+
+---
+### ArgoCD Setup
+
+> Kubernetes Cluster should be Running
+1. Create ArgoCD Namespace
+ ```
+ kubectl create namespace argocd
+ ```
+2. Apply ArgoCD Manifets
+ ```
+ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
+ ```
+3. Check ArgoCD Service
+ ```
+ kubectl get svc -n argocd
+ ```
+4. Service to NodePort
+ ```
+ kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "NodePort"}}'
+ ```
+5. Expose Port 8443
+ ```
+ kubectl port-forward -n argocd service/argocd-server 8443:443 --address=0.0.0.0 &
+ ```
+6. Firewall Expose
+ ```
+ sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+ sudo firewall-cmd --reload
+ ```
+7. Get ArgoCD Password
+ ```
+ kubectl get secret -n argocd argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo
+ ```
+ Use this in Login to ArgoCD
+
+8. You can use ArgoCD
+
+> Add all the things to start K8s.
+>
+> You need to first learn it!
+
+---
+### Prometheus & Grafana Setup
+
+> Install Helm
+
+1. Helm Repository Initilization
+ ```
+ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
+ helm repo add stable https://charts.helm.sh/stable
+ helm repo update
+ ```
+2. Creating a namespace
+ ```
+ kubectl create namespace monitoring
+ ```
+3. Paste this command
+ ```
+ helm install kind-prometheus prometheus-community/kube-prometheus-stack --namespace monitoring \
+ --set prometheus.service.nodePort=30000 \
+ --set prometheus.service.type=NodePort \
+ --set grafana.service.nodePort=31000 \
+ --set grafana.service.type=NodePort \
+ --set alertmanager.service.nodePort=32000 \
+ --set alertmanager.service.type=NodePort \
+ --set prometheus-node-exporter.service.nodePort=32001 \
+ --set prometheus-node-exporter.service.type=NodePort
+ ```
+4. Verify Deployments
+ ```
+ kubectl get pods -n monitoring
+ kubectl get svc -n monitoring
+ ```
+5. Port Forward
+ ```
+ kubectl port-forward svc/kind-prometheus-kube-prome-prometheus -n monitoring 9090:9090 --address=0.0.0.0 &
+ kubectl port-forward svc/kind-prometheus-grafana -n monitoring 31000:80 --address=0.0.0.0 &
+ ```
+6. Exposing Port
+ ```
+ sudo firewall-cmd --permanent --zone=public --add-port=9090/tcp
+ sudo firewall-cmd --permanent --zone=public --add-port=31000/tcp
+ sudo firewall-cmd --reload
+ ```
+> You are Ready to Go!
+
+---
\ No newline at end of file
diff --git a/dist/assets/GenreExplore.131e1e68.js b/dist/assets/GenreExplore.131e1e68.js
new file mode 100644
index 00000000..9a98ed15
--- /dev/null
+++ b/dist/assets/GenreExplore.131e1e68.js
@@ -0,0 +1 @@
+import{d as a,h as c,F as d,O as x,j as t,T as f,Q as u,b as h,C as m,w as g,x as b,y as p,R as y}from"./index.38b929df.js";import{V as v,w as I}from"./VideoItemWithHover.efba0917.js";function E(e,r){const[n,i]=a.exports.useState(null);return a.exports.useEffect(()=>{const s=new IntersectionObserver(([o])=>{i(o)},r!=null?r:{root:null,rootMargin:"0px",threshold:1});return e.current&&s.observe(e.current),()=>{e.current&&s.unobserve(e.current)}},[]),n}function M({genre:e,data:r,handleNext:n}){const i=a.exports.useRef(null),s=E(i);return a.exports.useEffect(()=>{s&&s.intersectionRatio===1&&r.page