Devops体系建设(一)

发布时间 2023-03-26 20:49:32作者: 羊大爷的专家之路

这是我的第一篇博客。

从写博客的念头开始,到目前为止已经足足6年了。

是的,整整耽误了6年。

这6年间,换了两份工作,体验了博士科研日常,拿到了软考的中高级证书和华为AI认证,工作内容从开发到测试再到总体,涉猎领域从自动化测试到网络安全再到Devops体系建设,负责范围从单打独斗的大头兵到拥有一支扩建中的专属小团队……

可以讲,变化了很多很多…

技术迭代太快了,要学习和掌握的知识每天都在更新,加之年龄的不断增长,为了使自己不再遗忘,正式起航博客机缘。

目前的规划是这样的,每周更新1篇,一年52篇,不一定非要解决了某个技术问题,完成了某种体系架构,哪怕是简简单单的搭建,也足以代表正在学习的状态。那么——

OK!Let’s GO!

就从一个安全问题入手吧。

此漏洞已于2019年9月被提交,故模拟GitlabCI靶场环境请使用之前版本。

用户越权访问Gitlab内部项目,Gitlab注册时会创建使用者账户并发送确认邮件,攻击者可通过创建私有存储库,而无需登录并触发管道运行。GitlabCI为每个Job生成惟一的作业令牌CI_JOB_TOKEN,该令牌为Job用户提供该目录所有项目的Visit、Read权限。攻击者修改.gitlab-ci.yml脚本,借助$CI_JOB_TOKEN环境变量,可以访问内部存储库,如果该Devops系统同时在.gitlab-ci脚本中部署了Sonarqube及SonarScanner操作,同样无需触发sonar-project.properties文件即可变更测试扫描结果。

首先需要部署GitlabCI、Sonarqube及Sonarsanner,以root用户登录到GitLab实例。

   

跳转至Area图标,选择Settings设置,在General下Sign-up restrictions注册限制处启用“注册时发送电子邮件”,并将注册文本白名单设置为example.com,保存。

 

退出GitlabCI,换被攻击人账号(victim用户)登录(被攻击人账号已提前申请),创建新项目,命名为“internal-project”,可见性设置为“internal”,并使用README复选框检查Initialize存储库,创建并保存该项目实例

 

  退出victim用户,注册攻击者attacker账户(攻击者已知道/猜测到白名单域名)。

 

创建Gitlab仓库及编写.gitlab-ci.yml脚本。

$ mkdir /tmp/test && cd /tmp/test 

$ git init 

$ echo "Hi" > README.md 

$ git add README.md 

$ git commit -m "Add readme" 

编写.gitlab-ci.Yml文件,克隆被攻击者内部项目存储库并上传到攻击者服务器。

 

添加.gitlab-ci.Yml文件到存储库,并将原始url设置为attack/test

 

最后Push到项目并启动攻击者服务器,然后攻击者成功访问了完整的git repo。

 

访问到数据后便可以调用.gitlab-ci脚本,进而影响Sonarqube、SonarScanner乃至sonar-project.properties脚本及软件操作。

 

无独有偶,以一个例子作为Devops的引子,近年来无论是IEEE explore、SCI Hub、Web of science,在EI的工程实例化方面都少不了Devops的影子。

 

通常用于构建Devops的两款工具:Jenkins和Gitlab,经过调研,主要对比和区别如下:

GitLabCI:轻量级,不需要复杂的安装手段;配置简单,与gitlab可直接适配;实时构建日志十分清晰,UI交互体验很好;使用 YAML 进行配置,任何人都可以很方便的使用;

没有统一的管理界面,无法统筹管理所有项目;配置依赖于代码仓库,耦合度没有Jenkins低;有助于DevOps人员,开发、测试、运维可以是同一个人,最便捷的开发方式。

Jenkins:编译服务和代码仓库分离,耦合度低。插件丰富,支持语言众多;插件以及自身安装较为复杂;体量较大,不是很适合小型团队;JenkinsCI适合在多角色团队中,职责分明、配置与代码分离、插件丰富。

鉴于试用便捷性等多方原因,博客暂时先以GitlabCI进行论述,Jenkins后续会配合自动化、流水线等进行补充。

GitlabCI部署分为RPM、Docker、K8S三种部署方式。

RPM方式:

wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-12.9.0-ce.0.el7.x86_64.rpm

rpm -ivh gitlab-ce-12.9.0-ce.0.el7.x86_64.rpm

vim /etc/gitlab.rb   # 编辑站点地址

gitlab-ctl reconfigure  # 配置

gitlab-ctl start

gitlab-ctl status

gitlab-ctl stop

   Docker方式:

wmkdir -p ~/data/gitlab/config ~/data/gitlab/logs ~/data/gitlab/data

docker pull gitlab/gitlab-ce:12.9.0-ce.0

docker run -d  -p 443:443 -p 80:80 -p 222:22 --name gitlab --restart always -v /Users/zeyang/data/gitlab/config:/etc/gitlab -v /Users/zeyang/data/gitlab/logs:/var/log/gitlab -v /Users/zeyang/data/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce:12.9.0-ce.0

docker exec -it gitlab bash

vim /etc/gitlab.rb  

gitlab-ctl reconfigure 

docker restart gitlab

docker start gitlab

docker stop gitlab

docker rm gitlab

K8S方式:

---

kind: Deployment

apiVersion: apps/v1

metadata:

labels:

  k8s-app: gitlab

  name: gitlab

  namespace: devops

spec:

  replicas: 1

  revisionHistoryLimit: 10

  selector:

    matchLabels:

      k8s-app: gitlab

 template:

    metadata:

      labels:

        k8s-app: gitlab

      namespace: devops

      name: gitlab

    spec:

      containers:

        - name: gitlab

          image: gitlab/gitlab-ce:12.6.0-ce.0

          imagePullPolicy: Always

          ports:

            - containerPort: 30088

              name: web

              protocol: TCP

            - containerPort: 22

              name: agent

              protocol: TCP

          resources:

            limits:

              cpu: 1000m

              memory: 4Gi

            requests:

              cpu: 500m

              memory: 512Mi

          livenessProbe:

            httpGet:

              path: /users/sign_in

              port: 30088

            initialDelaySeconds: 60

            timeoutSeconds: 5

            failureThreshold: 12

          readinessProbe:

            httpGet:

              path: /users/sign_in

              port: 30088

            initialDelaySeconds: 60

            timeoutSeconds: 5

            failureThreshold: 12

          volumeMounts:

            - name: gitlab-conf

              mountPath: /etc/gitlab

            - name: gitlab-log

              mountPath: /var/log/gitlab

            - name: gitlab-data

              mountPath: /var/opt/gitlab

          env:

            - name: gitlab_HOME

              value: /var/lib/gitlab

      volumes:

        - name: gitlab-conf

          hostPath:

            path: /data/devops/gitlab/config

            type: Directory

        - name: gitlab-log

          hostPath:

            path: /data/devops/gitlab/logs

            type: Directory

        - name: gitlab-data

          hostPath:

            path: /data/devops/gitlab/data

            type: Directory

      serviceAccountName: gitlab

---

apiVersion: v1

kind: ServiceAccount

metadata:

  labels:

    k8s-app: gitlab

  name: gitlab

  namespace: devops

---

kind: Service

apiVersion: v1

metadata:

  labels:

    k8s-app: gitlab

  name: gitlab

  namespace: devops

spec:

  type: NodePort

  ports:

    - name: web

      port: 30088

      targetPort: 30088

      nodePort: 30088

    - name: slave

      port: 22

      targetPort: 22

      nodePort: 30022

  selector:

    k8s-app: gitlab

---

kind: Role

apiVersion: rbac.authorization.k8s.io/v1beta1

metadata:

 name: gitlab

 namespace: devops

rules:

 - apiGroups: [""]

   resources: ["pods"]

   verbs: ["create","delete","get","list","patch","update","watch"]

 - apiGroups: [""]

   resources: ["pods/exec"]

   verbs: ["create","delete","get","list","patch","update","watch"]

 - apiGroups: [""]

   resources: ["pods/log"]

   verbs: ["get","list","watch"]

 - apiGroups: [""]

   resources: ["secrets"]

   verbs: ["get"]

---

apiVersion: rbac.authorization.k8s.io/v1beta1

kind: RoleBinding

metadata:

 name: gitlab

 namespace: devops

roleRef:

 apiGroup: rbac.authorization.k8s.io

 kind: Role

 name: gitlab

subjects:

 - kind: ServiceAccount

   name: gitlab

   namespace: devops

注意: 需要修改gitlab.rb配置文件中的IP地址,指定端口(不是必须的,同时之前要确定是否该端口是开放的),配置external_url及Nginx[“lixten_port”]参数。

只有Gitlab还无法将流水线跑起来,需要指定GitLabRunner。

添加官方仓库:

# For Debian/Ubuntu/Mint

curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash

# For RHEL/CentOS/Fedora

curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash

   安装版本,也可以自己指定。

# For Debian/Ubuntu/Mint

sudo apt-get install gitlab-runner=?//自己填写版本号

# For RHEL/CentOS/Fedora

sudo yum install gitlab-runner=?

Runner类型:

  • shared :运行整个平台项目的作业(gitlab)
  • group: 运行特定group下的所有项目的作业(group)
  • specific: 运行指定的项目作业(project)
  • locked: 无法运行项目作业
  • paused: 不会运行作业

获取shared类型Runner的token(通常用):

 

Runner注册:

docker run --rm -t -i -v ~/data/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner:v12.6.0 register

Runtime platform                                    arch=amd64 os=linux pid=6 revision=ac8e767a version=12.6.0

Running in system-mode.

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):

http://192.168.1.105

Please enter the gitlab-ci token for this runner:

4tutaeWWL3srNEcmHs1s

Please enter the gitlab-ci description for this runner:[00e4f023b5ae]:

 devops-service-runner

Please enter the gitlab-ci tags for this runner (comma separated):

build

Registering runner... succeeded                     runner=4tutaeWW

Please enter the executor: parallels, virtualbox, docker-ssh+machine, kubernetes, docker+machine, custom, docker, docker-ssh, shell, ssh:

shell

Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

也可以直接Docker注册:

docker run -itd --rm -v ~/data/gitlab-runner/config:/etc/gitlab-runner  gitlab/gitlab-runner:v12.6.0 register \

  --non-interactive \

  --executor "shell" \

  --url "http://192.168.1.200:30088/" \

  --registration-token "JRzzw2j1Ji6aBjwvkxAv" \

  --description "devops-runner" \

  --tag-list "build,deploy" \

  --run-untagged="true" \

  --locked="false" \

  --access-level="not_protected"

基础完成后,编写.gitlab-ci.yml脚本(编写过程参照语法),运行流水线,pass为通过。

 

        可以写的很多,鉴于篇幅原因,今日暂且至此,目前已完成GitlabCI与Nexus3、Salt、禅道、Jmeter、Sonarqube、Sonarscanner的联动,同时已在流水线中集成单元测试,目前支持对C/C++、Java、Python、Go五种常见语言的代码审计(包括安全审计)及质量检测。

        后续将逐一展开记录,最后,使用IEEE TRANSACTIONS ON SOFTWARE ENGINEERING最新TRANS论文对Devops整体趋势和能力体系的囊括图做结尾,与君共勉!