AWS CodeBuild 作为非根用户

AWS CodeBuild as non-root user

有没有办法在 AWS CodeBuild 上删除 root 用户? 我们正在构建一个 Yocto 项目,如果我们是 root(Bitbake 完整性检查),该项目在 CodeBuild 上会失败。

我们的孤注一掷的方法也不管用:

...

build:
  commands:
    - chmod -R 777 $(pwd)/ && chown -R builder $(pwd)/ && su -c "$(pwd)/make.sh" -s /bin/bash builder
...

失败:

bash: /codebuild/output/src624711770/src/.../make.sh: Permission denied

知道我们如何 运行 这是一个非 root 用户吗?

感谢您提出此功能请求。目前,您不能 运行 作为 CodeBuild 中的非根用户,我已将其传递给团队进行进一步审查。非常感谢您的反馈。

我们最终做了以下事情:

创建一个 Dockerfile,其中包含构建 Yocto / Bitbake 项目的所有内容,我们在其中 ADD 所需的源并创建一个用户 builder,我们用它来构建我们的项目。

  FROM ubuntu:16.04

  RUN apt-get update && apt-get -y upgrade

  # Required Packages for the Host Development System
  RUN apt-get install -y gawk wget git-core diffstat unzip texinfo gcc-multilib \
       build-essential chrpath socat cpio python python3 python3-pip python3-pexpect \
       xz-utils debianutils iputils-ping vim

  # Additional host packages required by poky/scripts/wic
  RUN apt-get install -y curl dosfstools mtools parted syslinux tree

  # Create a non-root user that will perform the actual build
  RUN id builder 2>/dev/null || useradd --uid 30000 --create-home builder
  RUN apt-get install -y sudo
  RUN echo "builder ALL=(ALL) NOPASSWD: ALL" | tee -a /etc/sudoers

  # Fix error "Please use a locale setting which supports utf-8."
  # See https://wiki.yoctoproject.org/wiki/TipsAndTricks/ResolvingLocaleIssues
  RUN apt-get install -y locales
  RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
          echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
          dpkg-reconfigure --frontend=noninteractive locales && \
          update-locale LANG=en_US.UTF-8

  ENV LC_ALL en_US.UTF-8
  ENV LANG US.UTF-8
  ENV LANGUAGE en_US.UTF-8

  WORKDIR /home/builder/
  ADD ./ ./

  USER builder

  ENTRYPOINT ["/bin/bash", "-c", "./make.sh"]

我们在 Codebuild pre_build 步骤中构建此 docker 并且 运行 在 ENTRYPOINT(在 make.sh 中)的实际构建当我们 运行 图像。容器被激发后,我们将artifacts复制到Codebuild主机上并放在S3上:

version: 0.2

phases:
  pre_build:
    commands:
      - mkdir ./images
      - docker build -t bob .
  build:
    commands:
      - docker run bob:latest
  post_build:
    commands:
      # copy the last excited container's images into host as build artifact
      - docker cp $(docker container ls -a | head -2 | tail -1 | awk '{ print  }'):/home/builder/yocto-env/build/tmp/deploy/images ./images
      - tar -cvzf artifacts.tar.gz ./images/*
artifacts:
  files:
    - artifacts.tar.gz

这种方法的唯一缺点是我们不能(轻松地)使用 Codebuild 的缓存功能。但是构建对我们来说已经足够快了,因为我们在白天进行本地构建,基本上在晚上从头开始重建,大约需要 90 分钟(在最强大的 Codebuild 实例上)。

唉,所以我遇到了这个问题,我很失望这个问题没有好的或简单的答案。有许多进程强烈反对 运行 作为 root 用户,如 composer 和其他 flat-out 拒绝用户的进程,如 wp-cli。如果您使用的是 AWS 提供的 Ubuntu "standard image",那么 /etc/passwd 文件中似乎有一个现有用户 dockremap:x:1000:1000::/home/dockremap:/bin/sh。我认为此用户是 docker 中的 userns-remap,我不确定它是否可用。令人惊讶的是,另一个未被提及的选项是 运行 useradd -N -G users develop,用于在容器中创建新用户。它比为如此微不足道的事情启动自定义容器要简单得多。

对于 运行 CodeBuild,您需要使用 buildspec.yaml 中的 运行-as 标记指定一个 Linux 用户名,如 [=11] 中所示=]

version: 0.2

run-as: Linux-user-name

env:
  variables:
   key: "value"
   key: "value"
parameter-store:
key: "value"
key: "value"

phases:
  install:
  run-as: Linux-user-name
  runtime-versions:
    runtime: version

我在 AWS CodeBuild 中成功使用非根用户。
要提出一个实用的解决方案,需要的不仅仅是了解一些 CodeBuild 选项。

每个人都应该发现 run-as 选项 quite easily
下一个问题是"which user?";您不能只输入任何单词作为用户名。

为了找出可用的用户,下一条线索在 Docker images provided by CodeBuild 部分。在那里,您会找到每个图像定义的 link。 对我来说,link 将我带到 this page on GitHub
查看 Dockerfile 的源代码后,我们会知道有一个名为 codebuild-user 的用户可用。我们可以将此 codebuild-user 用于构建规范中的 run-as

然后我们将面临很多其他问题,因为标准映像仅安装 root 的每种语言的运行时。 这是一般性解释所能达到的范围。

对我来说,我想使用 Ruby 运行时,所以我唯一关心的是 Ruby 运行时。 如果您将 CodeBuild 用于其他用途,那么您现在只能靠自己了。

为了利用 Ruby 运行时作为 codebuild-user,我们必须从 root 用户公开它们。为此,我使用以下命令更改了 CodeBuild 映像使用的 .rbenv 所需的权限和所有者。

chmod +x ~
chown -R codebuild-user:codebuild-user ~/.rbenv


bundler(Ruby 的依赖管理工具)仍然想访问不可写的主目录。我们必须设置一个环境变量以使其使用其他可写位置作为主目录。 环境变量是BUNDLE_USER_HOME.

把所有东西放在一起;我的构建规范看起来像:

version: 0.2

env:
  variables:
    RAILS_ENV: test
    BUNDLE_USER_HOME: /tmp/bundle-user
    BUNDLE_SILENCE_ROOT_WARNING: true

run-as: codebuild-user

phases:
  install:
    runtime-versions:
      ruby: 2.x
    run-as: root
    commands:
      - chmod +x ~
      - chown -R codebuild-user:codebuild-user ~/.rbenv
      - bundle config set path 'vendor/bundle'
      - bundle install
  build:
    commands:
      - bundle exec rails spec

cache:
  paths:
    - vendor/bundle/**/*

我的观点是:

  • 确实有可能。
  • 显示我是如何为我的用例做的。