封装make, rm, 提高编译的安全, 防止意外使用root权限.

背景:

   我在一家创业的公司, 公司开发机使用的是一台linux服务器, 多人公用, svn服务各内部管理平台的服务器也在这台机器上, 因此这台机器变得非常的重要. 虽然svn和数据库有定期备份,但不是天天备份. 数据一旦出现问题, 影响还是很大的.

   作为小组的核心成员我拥有root密码, 偶尔会在这台开发机上用root权限装一些库, 升级工具, 部署几个管理平台(包括一些数据库的操作)什么的.  操作安全就是一个很重要的事情.

 

小心问题:

  在之前的公司做服务器软件开发的时候, 受到过很多教育指导, 深知不要乱用root权限.  那个时候公司的权限管理不是很严格, 而server组作为核心组和以技术相对比较强健自称(也是事实), 相对来说使用root权限就更多 以前有同事在开发机上干过rm -rf / 这种事情, 当时我自己作为新人也干过用root手工替换升级stdc++的库文件失败导致用光盘去恢复系统的情况. 因此每每使用rm的时候都是小心翼翼, 后来也是非常的有信心, 不会乱删东西.

 

问题还是出现了:

   今天早上, 我在公司用自已的账号去做一个源代码目录转移的工作, 转移完毕后. 为了检查结果, 做了一下make, 实然就哗哗的开始刷屏, 赶紧定睛一看, 卖糕的, 居然是在删除服务器上的根目录下的数据, 还好是用自己的账号登录的, 并没有权限删除那些数据.  还好我只是转移自己的代码. 要是整理公司代码使用root并没有换回普通账号就直接编译, 后果将不堪设想. 回想起以前有时su后忘了退出, 偶尔还是会用root编译自己的代码 . 就直冒冷汗, 于是马上决定解决这个问题.

 

找到原因 :

   仔细看了一下makefile, 找到问题, 这是一个很多人喜欢写的makefile的方式, 包括几大互联网公司, 这种makefile的代码到处都是, 关键部分如下:

   include ../makefile.common

 

   SUB_PROJECT: sub1 sub2 .....

   .....

   .....

   all: dir clean

         ....

 

   dir:
      if [ ! -d $(OUTPUT_PATH) ]; then mkdir $(OUTPUT_PATH); fi
      if [ ! -d $(TARGET_INC_PATH) ]; then mkdir $(TARGET_INC_PATH); fi
      if [ ! -d $(TARGET_LIB_PATH) ]; then mkdir $(TARGET_LIB_PATH); fi

 

   clean: dir

     @for d in $(SUB_PROJECT) ; do /
     make clean -C $$d ; /
     echo "" ;/
     done
     @echo ""
     rm -rf $(OUTPUT_PATH) /*

  

作一个简单说明:

1. 部分的关键路径的定义, 包含在另一个文件中. 比如这里的$(OUTPUT_PATH)

2. 使用rm -rf这样的命令删除特定目录下的所有的字目录, 有的公司会把rm用别名的方式换成"rm -i", 所以有人为了在删目录时方便, 使用了-rf 这样危险的参数.

3 .这些命令还经常会被用到. 特别是在预发布程序时. 这些可能目录会上传到编译机上编译, 甚至用高权限编译(比如某用"掌"为图标的公司)

 

这次的问题就在这里. 我没有把这个包含的文件放到正确的路径下, 因此直接导致了$(OUTPUT_PATH)为未定义的. 而那个rm语句很显然就成了rm -rf /*....  让人汗颜.

 

反省自己的坏习惯并分析:

  平时因为不光使用公司的linux开发机, 自己有也装了多个ubuntu系统的机器作为开发机, ubuntu默认是不会开root密码的. 所有的高权限命令要使用sudo来完成, 但是却开放了sudo su这种命令, 有时我一次要装多个库时, 为了图方便, 经常使用sudo su升级到root做操作, 但与sudo直接执行不同, sudo一次后, 只有一小段时间是有权限不用输入密码做高级操作的.  而sudo su后, 因为其实su开启的shell只要不退出, 就会一直有高权限, 之后的操作会非常危险. 而在公司, 我也经常直接su进行系列的操作, 可能产生的破坏性就更大了.

 

解决办法

1 . 改正习惯, 但这个很难说, 因此要用下面更强硬的手段, 让自己就算不方便 也不能出现危险事件.

 

2. 严格限制可以sudo的账号,

   包括

   1>尽量减少可以使用sudo的相关人员, 即: 使用ubuntu的方式, 并不是使用root密码来sudo, 而是开一个可以sudo的账号, 必须先su成这个账号, 再才能sudo, 

   2>将root改成随机密码, 防止直接su到root, 禁用sudo的权限,防止通过sudo su来得到高权限.

 

3. 把make改名. 然后写程序对make进行封装, 程序流程如下:

    <1>  检查自己是不是root, 如果不是, 直接调用原make, 结束

    <2>  如果是root, 强制要求输入一串文本比如"我知道我用的是ROOT,并对危险可以预见", 否则不能进行

    <3>  打开特定的文件, 比如/var/make/pid, 

           (a)防止多个终端用root编译, 在这个特定文件上是要加锁, 并写入TTY信息, 若已经有tty信息且不相符, 则中止此次编译

           (b)考虑到make是可以嵌套的, 写入一个计数, 可以写入本次嵌套的相关信息. 

           (c)标志已经是root, 这样在嵌套编译时, 不用再次输入

     <4>  每次一个嵌套的make进入和退出时, 做一下附加的检查, 看是否这个文件在make过程中被改动和信息是否正确, 如果有任何改动, 则提示并退出编译. 这主要是考虑到: 1 很难限制有人用root更改此文件, 2 有时必须要更改此文件, 比如编译过程中死机或异常退出导致文件没有被清理. 应当手动删除. 3 其它TTY下的ROOT账户在不知正在进行编译的情况下删除或更改此文件

     <5> 编译完毕后, 删除此文件或标记已经退出 . 下次make的时候 必须要重新检查和输入

 

4. 封装rm命令, 检查少数特定的安全目录(可以从配置文件读取), 如果有, 则强制要求确认.  再执行删除操作

 

 

通过以上几点, 基本上可以防止误操作, 甚至是上文提到隐藏的误操作带来的意外,

 

当然, 恶意的破坏还是很难防的. 就不在这次的讨论范围内了

 

你可能感兴趣的:(服务器开发与管理,makefile,path,output,ubuntu,服务器软件,服务器)