目錄

  1. 專案概述
  2. 前置需求
  3. 第一階段:基礎設施設置
  4. 第二階段:應用設置與容器化
  5. 第三階段:使用 Jenkins CI/CD 自動化
  6. 第四階段:使用 HashiCorp Vault 保護機密資料
  7. 第五階段:Kubernetes 部署
  8. 第六階段:Kubernetes 中的安全加固
  9. 結論

專案概述

在這個 DevSecOps 專案中,您將使用 JenkinsDockerKubernetesHashiCorp Vault 部署一個安全的全棧 Node.js 網頁應用程式。專案將重點自動化整個部署過程,並在每個階段整合安全措施。我們將掃描 Docker 映像中的漏洞,安全地管理敏感資訊,並在 Kubernetes 叢集中部署應用程式,確保安全性貫穿始終。


前置需求

  1. AWS 帳戶(用於託管 EKS Kubernetes 叢集)。
  2. 本地或雲端的 Jenkins 伺服器。
  3. 在您的本地機器上安裝 Docker 和 Kubernetes CLI (kubectl)。
  4. 安裝 Terraform 以進行基礎設施配置。
  5. 安裝 HashiCorp Vault 以管理機密資料。
  6. 對 Node.js、Docker、Kubernetes 和 Jenkins 有基本了解。

第一階段:基礎設施設置

1.1 配置 Kubernetes 叢集 (EKS)

我們將使用 Terraform 在 AWS 上配置 EKS(彈性 Kubernetes 服務)叢集。

a. 安裝 Terraform:
# 安裝 Terraform (Linux/macOS)
wget https://releases.hashicorp.com/terraform/1.0.11/terraform_1.0.11_linux_amd64.zip
unzip terraform_1.0.11_linux_amd64.zip
sudo mv terraform /usr/local/bin/
terraform --version
b. 定義 Terraform 配置:

創建一個名為 eks-cluster.tf 的檔案,用於配置 EKS 叢集。

provider "aws" {
  region = "us-west-2"
}

resource "aws_eks_cluster" "my_cluster" {
  name     = "devsecops-cluster"
  role_arn = aws_iam_role.eks_role.arn

  vpc_config {
    subnet_ids = [aws_subnet.subnet1.id, aws_subnet.subnet2.id]
  }
}

resource "aws_iam_role" "eks_role" {
  name = "eks-role"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}
c. 應用 Terraform 配置:
terraform init
terraform apply

叢集建立完成後,配置 kubectl 以指向您的新叢集:

aws eks --region us-west-2 update-kubeconfig --name devsecops-cluster

1.2 設置 Jenkins 伺服器

在本地機器或雲端伺服器上安裝 Jenkins。Jenkins 將自動化我們的 Node.js 應用程式的構建、測試和部署。

a. 安裝 Jenkins:
# 安裝 Java(Jenkins 所需)
sudo apt update
sudo apt install openjdk-11-jdk

# 添加 Jenkins 倉庫並安裝 Jenkins
wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt update
sudo apt install jenkins

# 啟動 Jenkins
sudo systemctl start jenkins
sudo systemctl enable jenkins

安裝後,配置 Jenkins 插件以進行 Kubernetes、Docker 和 Vault 整合。


第二階段:應用設置與容器化

2.1 Node.js 網頁應用程式 (原始碼)

對於這個專案,我們將使用一個簡單的 Node.js 網頁應用程式。創建以下檔案:

app.js:
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.send('Hello from DevSecOps Node.js App!');
});

app.listen(port, () => {
  console.log(`App listening at http://localhost:${port}`);
});
package.json:
{
  "name": "devsecops-nodejs-app",
  "version": "1.0.0",
  "description": "A simple Node.js app for DevSecOps project",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "^4.17.1"
  }
}

運行 npm install 以安裝依賴項:

npm install

2.2 創建 Dockerfile

創建一個 Dockerfile 用於容器化 Node.js 應用。

# 使用官方 Node.js 執行環境作為父映像
FROM node:14

# 設置工作目錄
WORKDIR /usr/src/app

# 複製 package.json 並安裝依賴項
COPY package*.json ./
RUN npm install

# 將應用程式源碼打包
COPY . .

# 開放應用程式埠
EXPOSE 3000

# 執行應用程式
CMD ["npm", "start"]

2.3 構建與測試 Docker 映像

a. 構建 Docker 映像:
docker build -t devsecops-nodejs-app .
b. 在本地運行 Docker 容器:
docker run -p 3000:3000 devsecops-nodejs-app

訪問 http://localhost:3000 以查看運行中的應用。


第三階段:使用 Jenkins CI/CD 自動化

3.1 Jenkins 管道設置

設置 Jenkins 管道以自動構建 Docker 映像、掃描漏洞、將映像推送到 DockerHub,並部署到 Kubernetes。

在您的專案庫中創建一個 Jenkinsfile

pipeline {
    agent any

    stages {
        stage('Clone Repository') {
            steps {
                git 'https://github.com/your-repo.git'
            }
        }

        stage('Build Docker Image') {
            steps {
                script {
                    docker.build("devsecops-nodejs-app:${env.BUILD_ID}")
                }
            }
        }

        stage('Security Scan') {
            steps {
                // 使用 Trivy 掃描 Docker 映像中的漏洞
                sh 'docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy:latest image devsecops-nodejs-app:${env.BUILD_ID}'
            }
        }

        stage('Push Image to DockerHub') {
            steps {
                script {
                    docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-credentials') {
                        docker.image("devsecops-nodejs-app:${env.BUILD_ID}").push()
                    }
                }
            }
        }

        stage('Deploy to Kubernetes') {
            steps {
                kubernetesDeploy(kubeconfigId: 'kubeconfig', configs: 'k8s/deployment.yaml', enableConfigSubstitution: true)
            }
        }
    }
}

第四階段:使用 HashiCorp Vault 保護機密資料

整合 HashiCorp Vault 以安全管理敏感數據,如資料庫憑證、API 金鑰和令牌。

4.1 安裝 HashiCorp Vault:

# 安裝 Vault
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install vault

4.2 配置 Vault 用於 Kubernetes:

vault auth enable kubernetes
vault write auth/kubernetes/config \
    token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
    kubernetes_host="https://$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.server}')" \
    kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

第五階段:Kubernetes 部署

在這一階段,我們將使用 Kubernetes 清單Node.js 應用程式部署到 Kubernetes 叢集。部署過程包括創建資源,如 DeploymentService 對象,定義我們的應用如何在叢集中運行。

5.1 創建 Kubernetes 部署檔案 (deployment.yaml)

Deployment 資源確保所需數量的應用實例(Pods)正在運行。如果一個 Pod 失敗,Kubernetes 將自動重新創建以滿足指定的副本計數。

創建一個名為 deployment.yaml 的檔案,內容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: devsecops-nodejs-app
  labels:
    app: devsecops-nodejs-app
spec:
  replicas: 3  # 我們將運行 3 個應用實例 (Pods)
  selector:
    matchLabels:
      app: devsecops-nodejs-app
  template:
    metadata:
      labels:
        app: devsecops-nodejs-app
    spec:
      containers:
      - name: devsecops-nodejs-container
        image: your-dockerhub-username/devsecops-nodejs-app:latest  # 使用您的 DockerHub 倉庫
        ports:
        - containerPort: 3000
        env:
        - name: SECRET_MESSAGE
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: secret-message  # 會通過 Kubernetes 機密從 Vault 獲取秘密值
---
apiVersion: v1
kind: Service
metadata:
  name: devsecops-nodejs-service
spec:
  selector:
    app: devsecops-nodejs-app
  ports:
  - protocol: TCP
    port: 80  # 將服務暴露在 80 埠上
    targetPort: 3000  # 內部轉發流量到容器的 3000 埠
  type: LoadBalancer  # 將應用暴露到互聯網

5.2 部署應用程式

現在,使用 kubectl 將應用程式部署到 Kubernetes 叢集中。

a. 應用部署和服務:
kubectl apply -f deployment.yaml
b. 驗證部署:
kubectl get deployments
c. 檢查 Pods:
kubectl get pods
d. 獲取服務的外部 IP:
kubectl get services

一旦服務運行,您可以使用負載均衡器提供的外部 IP 地址訪問 Node.js 應用。

5.3 使用 Kubernetes 處理機密資料

Deployment 清單中,我們引用了 Kubernetes Secret 對象,該對象由 HashiCorp Vault 安全管理。我們將 Vault 與 Kubernetes 整合,以便在運行時安全注入敏感數據,例如 API 金鑰、密碼或資料庫憑證到 Pods。

要在 Kubernetes 中創建一個機密,可以運行:

kubectl create secret generic app-secret \
  --from-literal=secret-message="This is a secret from Vault!"

此機密將通過環境變數 SECRET_MESSAGE 傳遞給應用容器,您的應用可以安全地讀取它。


第六階段:Kubernetes 中的安全加固

在這一階段,我們將通過實施 PodSecurityPoliciesRBACNetwork Policies 來增強 Kubernetes 部署的安全性。

6.1 PodSecurityPolicies (PSP)

PodSecurityPolicies 用於控制 Pod 的安全層面,例如特權容器執行、卷類型、主機網絡等。您可以創建一個政策,以防止容器以 root 使用者身份運行。

範例 PodSecurityPolicy (pod-security-policy.yaml):
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted-psp
spec:
  privileged: false
  runAsUser:
    rule: MustRunAsNonRoot
  fsGroup:
    rule: MustRunAs
    ranges:
    - min: 1
      max: 65535
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: MustRunAs
    ranges:
    - min: 1
      max: 65535
  volumes:
  - configMap
  - secret

將政策應用到 Kubernetes 叢集:

kubectl apply -f pod-security-policy.yaml

6.2 基於角色的存取控制 (RBAC)

RBAC 允許在 Kubernetes 中進行細粒度的存取控制。定義授予用戶或服務特定權限的角色。

範例 RBAC 配置 (rbac.yaml):
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: app-deployer
rules:
- apiGroups: ["apps", "extensions"]
  resources: ["deployments"]
  verbs: ["create", "update", "delete"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-deployer-binding
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: app-deployer
subjects:
- kind: User
  name: jenkins  # 將部署應用程式的 Jenkins 服務帳戶
  apiGroup: rbac.authorization.k8s.io

應用 RBAC 政策:

kubectl apply -f rbac.yaml

6.3 網路策略

網路策略 定義允許或拒絕 Pod 之間通信的流量規則。使用它們可以確保 Pod 之間的通信安全,並限制對應用的訪問。

範例網路策略 (network-policy.yaml):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-only-internal-traffic
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: devsecops-nodejs-app
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: internal-service

這項政策限制對 devsecops-nodejs-app Pods 的流量,僅允許來自標記為 internal-service 的 Pods 的通信。

應用網路策略:

kubectl apply -f network-policy.yaml

結論

這個專案展示了使用 Jenkins、Docker、Kubernetes 和 HashiCorp Vault 完整的 Node.js 應用程式安全部署過程。通過整合漏洞掃描和機密管理等安全實踐,我們確保應用程序在生產環境中安全部署。


👤 作者

banner

加入我們的 Telegram 社群 || Follow me on GitHub 獲取更多 DevOps 內容!


原文出處:https://dev.to/prodevopsguytech/devsecops-project-secure-full-stack-nodejs-web-application-deployment-with-jenkins-docker-kubernetes-and-hashicorp-vault-166


共有 0 則留言