Jenkins sudo:终端需要读取密码

0yycz8jy  于 2023-03-29  发布在  Jenkins
关注(0)|答案(2)|浏览(319)

我有一个FastAPI应用程序,我已经为其配置了Jenkins管道。当我在启用代码覆盖率的情况下执行单元测试时,它们会失败,并出现以下错误:

Started by user gold
Obtained Jenkinsfile from git https://github.com/edtshuma/devsecops-labs.git
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/Python-DevSecOps
....
....
[Pipeline] sh
+ pip install -r requirements.txt
....
Requirement already satisfied: uvicorn==0.20.0 in ./.pyenv-usr-bin-python3.8/lib/python3.8/site-packages (from -r requirements.txt (line 41)) (0.20.0)
Requirement already satisfied: watchfiles==0.18.1 in ./.pyenv-usr-bin-python3.8/lib/python3.8/site-packages (from -r requirements.txt (line 42)) (0.18.1)
Requirement already satisfied: websockets==10.4 in ./.pyenv-usr-bin-python3.8/lib/python3.8/site-packages (from -r requirements.txt (line 43)) (10.4)
+ sudo chown -R jenkins:jenkins ./docs/unit-tests/htmlcoverage
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
[Pipeline] }
[Pipeline] // withPythonEnv

Jenkins菲尔

pipeline {
 agent any
  
triggers {
    githubPush()
}
stages {
    
    stage('Setup'){
       steps{
       withPythonEnv('/usr/bin/python3.8') {
            sh 'echo "Job is starting" '
        }            
        }
     }    
stage('Unit Tests'){ 
           steps{
               withPythonEnv('/usr/bin/python3.8') {
                 sh '''pip install -r requirements.txt
                       sudo chown -R jenkins:jenkins ./docs/unit-tests/htmlcoverage
                       pytest -v --junitxml=docs/unit-tests/htmlcoverage/coverage.xml --cov-report xml --cov app.main
                '''
             }           
            }                    
         }                
       stage('Publish Test Report'){ 
           steps{
              cobertura autoUpdateHealth: false, autoUpdateStability: false, coberturaReportFile: 'coverage*.xml', conditionalCoverageTargets: '70, 0, 0', failUnhealthy: false, failUnstable: false, lineCoverageTargets: '80, 0, 0', maxNumberOfBuilds: 0, methodCoverageTargets: '80, 0, 0', onlyStable: false, sourceEncoding: 'ASCII', zoomCoverageChart: false
              archiveArtifacts artifacts: 'docs/unit-tests/htmlcoverage/*.*'
            }                    
         }        

      }
}

我添加了 sudo chown -R jenkins:jenkins ./docs/unit-tests/htmlcoverage 行,因为我遇到了覆盖文件的权限错误:

INTERNALERROR> PermissionError: [Errno 13] Permission denied: 'coverage.xml'

我还验证了coverage.xml是root用户,而不是常规的jenkins用户(是什么原因导致的?):

我尝试过的:

echo “jenkins ALL=(ALL) NOPASSWD: ALL” >> /etc/sudoers

这将导致相同的错误sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper

echo “jenkins ALL= NOPASSWD: ALL” >> /etc/sudoers

这也会导致相同的错误sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
在这两种情况下,我都重新启动了jenkins服务。jenkins用户也已经添加到sudo组。
我到底错过了什么

68de4m5k

68de4m5k1#

由于docs文件夹属于root,所以需要root来清理,可以添加临时stage来清理,如下所示,一旦确定管道不会使用root,就可以移除临时stage

stage('Clean Test Report') {
    steps {
        sh '''
            docker run -t \
                -u root \
                -v "$(pwd)":"$(pwd)" \
                -w "$(pwd) \
                --entrypoint='' \
                <what ever a docker image> \
                rm -rf docs
        '''
    }
}

stage('Unit Tests'){ 
   steps{
       withPythonEnv('/usr/bin/python3.8') {
         sh '''
            ls -al
            pip install -r requirements.txt
            pytest -v \
                --junitxml=docs/unit-tests/htmlcoverage/coverage.xml \
                --cov-report xml \
                --cov app.main
        '''
     }           
    }                    
}

要阻止管道以root用户身份运行容器,可以执行以下操作

# run container by sh step
sh '''
  docker run \
    -u $(id -u):$(id -g) \
    -v /etc/passwd:/etc/passwd \
    ...
'''

# run container by docker global variable
container = docker.image(<image>).run(
    '-u $(id -u):$(id -g) -v /etc/passwd:/etc/passwd -t', 
    'cat'
)

docker.image(<image>).withRun(
   '-u $(id -u):$(id -g) -v /etc/passwd:/etc/passwd -t', 'cat') { container ->
   sh """
      docker exec -it ${container.id} -c \
        "pip install .. \
         pytest ..
        "
   """
}

docker.image(<image>).inside('-v /etc/passwd:/etc/passwd') {
# inside() run container as current host user by default

   sh '''
      pip install .. \
      pytest ...
   '''
}

# specify container as agent
# which runs container as current host user by default
agent {
   docker {
     args: '-v /etc/passwd:/etc/passwd'
   }   
}

agent {
   dockerfile {
     args: '-v /etc/passwd:/etc/passwd'
   }   
}
uqcuzwp8

uqcuzwp82#

对于任何正在努力解决这个问题的人来说,问题在于/etc/sudoers内部的规则优先级。
默认情况下 * 如果/etc/sudoers文件中有多个用户条目,sudo将使用最后一个规则 *
由于规则在/etc/sudoers中的位置,对jenkins用户的更改被覆盖:
错误

这是错误的,因为jenkins user已经是sudo组的成员,因此jenkins ALL=(ALL) NOPASSWD: ALL行将被行覆盖

sudo ALL=(ALL:ALL) ALL

正确

相关问题