Jenkins restrict Jenkinsfile modifications on pull request - jenkins

I have a GitHub repo setup with a Jenkinsfile. The GitHub Organization Folder Plugin will execute the pipeline from the supplied Jenkinsfile.
The final step of the pipeline is the deploy step. The deploy step checks if the branch has AWS credentials using the CloudBees Amazon Web Services Credentials Plugin. If it detects credentials it will deploy otherwise it won't.
All members have read only access to the GitHub repository, whenever they want to change something they have to create a pull request.(Only admins can merge) If there is a new pull request the Jenkins server will run the pipeline until the deploy step, to check if the pull request can be integrated to the master branch. The finalstep of the pipeline is the deploy step, this shouldn't be executed for pull requests.
stage('Deploy') {
// Deploy with the right credentials
try {
withCredentials([[
$class: 'AmazonWebServicesCredentialsBinding',
accessKeyVariable: 'AWS_ACCESS_KEY_ID',
credentialsId: env.BRANCH_NAME + '_AWS_Credentials',
secretKeyVariable: 'AWS_SECRET_ACCESS_KEY'
]]) {
echo("Deploying to " + env.BRANCH_NAME + "...")
...
}
} catch(all) {
echo("Not deploying for branch: " + env.BRANCH_NAME)
}
}
The problem is that team members can create a pull request with a changed Jenkinsfile.
So let's say one of the team members get's hacked. They can now infect the production environment by creating a pull request with a changed Jenkinsfile which does the following:
credentialsId: 'master_AWS_Credentials',
How do I prevent Jenkins from running the pipeline for a changed Jenkinsfile?
Or how do I make pull request use the Jenkinsfile from the master branch instead?

As far as I know it is not documented, but only a pull request from a branch of the repository can execute a changed JenkinsFile.
If someone make a fork and a pull request, the Jenkins file exectued by Jenkins will be the one of the targeted branch of the pull request, and not the one of the pull request.
If admins level is required to merge anything (not only the master branch) so you are safe.

you probably forgot to add the handler for the jenkins file, look at the repository to get the setting of the preventation. Hope this will fix it for you.

Related

How to set sonar url commonly for all the multibranch pipeline jobs(created via bitbucket organization job) commonly?

I am using organization "Organizational Folder" in jenkins and able to create multibranch pipeline jobs for all my repos available in my organization folder in bitbucket.
Each of the repos contains Jenkinsfile because of which the job gets created. Now I am stuck at a point, I want to publish sonar report of all the repos but it is trying to publish at sonar default url. One solution I am aware of is to provide sonar url and login credentials in each of the Jenkinsfile. But I don't want to do that as I will have to make changes in more than 50 repos.
I am using shared instance of Jenkins, thus, does not have admin access to configure settings.xml for maven.
Is there any way by which I can pass sonar url and credentials to all the multibranch pipeline jobs via configuration in "Organizational Folder" or at the folder level where I have admin access
You can define sonarQube server in environment section of jenkinsfile and also create token on sonarQube and add it in credentials of jenkins and use it like this
environment {
SONAR_URL = "https://YOUR_SONARQUBE_URL"
SONAR_TOKEN = credentials('ID_OF_YOUR_CREDENTIALS')
}
stage("Run SonarQube Analysis") {
steps {
script {
sh 'mvn clean package sonar:sonar -Dsonar.host.url=$SONAR_URL -Dsonar.login=$SONAR_TOKEN -Dsonar.profile="Sonar way"'
}
}
}

Jenkins Pipeline not providing Bitbucket Server environment variables

How can I configure my Jenkins Pipeline project to provide the CHANGE_* variables related to a Bitbucket Server commit? The project's Pipeline definition is Pipeline script from SCM (Bitbucket Server Integration).
I have checked Bitbucket Server trigger build after push made available from the Bitbucket Server Integration Jenkins plugin and the build does get triggered, but the variables related to the commit/change message, author, author email, etc. are all missing.
pipeline {
agent any
stages {
stage("Hello variables") {
steps {
sh 'printenv'
}
}
}
}
The only Bitbucket related env variables are GIT_BRANCH, GIT_COMMIT, and GIT_URL.
The Bitbucket webhook (trigger) plugin does not provide a json payload.
If you want to get Bitbucket trigger json payload (and query it inside the the pipeline) you'll need to use the Generic Webhook Trigger

Jenkins Multibranch pipeline pull request

I am using multibranch pipeline for pullrequest. When a pr is created it triggers the pullrequest job. Is there anyway to trigger the job only on specific pull requests instead of all.
example: I have three branches develop, fb and master. I want to trigger the job only when I create a pull request from develop to master, not when I create a pullrequest from fb to develop or fb to master.
In this case you may want to run your pipeline, analyze the base branch, and stop if the base branch is not to your liking.
The environment variable CHANGE_ID is set by the github branch source plugin in case the branch is a pull request.
If it's set, you can explore the global object named pullRequest, e.g. like this:
if (env.CHANGE_ID) {
echo("Looking for PR: PR detected, change id is ${env.CHANGE_ID}")
def prBase = pullRequest.base
if (prBase != 'master') {
currentBuild.result = 'ABORTED'
error("This PR is over ${prBase} branch, not 'master'. Aborting.")
}
}

What does the pollSCM trigger refer to in this Jenkinsfile?

Consider the following setup using Jenkins 2.176.1:
A new pipeline project named Foobar
Poll SCM as (only) build trigger, with: H/5 * * * * ... under the assumption that this refers to the SCM configured in the next step
Pipeline script from SCM with SCM Git and a working Git repository URL
Uncheck Lightweight checkout because of JENKINS-42971 and JENKINS-48431 (I am using build variables in the real project and Jenkinsfile; also this may affect how pollSCM works, so I include this step here)
Said repository contains a simple Jenkinsfile
The Jenkinsfile looks approximately like this:
#!groovy
pipeline {
agent any
triggers { pollSCM 'H/5 * * * *' }
stages {
stage('Source checkout') {
steps {
checkout(
[
$class: 'GitSCM',
branches: [],
browser: [],
doGenerateSubmoduleConfigurations: false,
extensions: [],
submoduleCfg: [],
userRemoteConfigs: [
[
url: 'git://server/project.git'
]
]
]
)
stash 'source'
}
}
stage('OS-specific binaries') {
parallel {
stage('Linux') {
agent { label 'gcc && linux' }
steps {
unstash 'source'
echo 'Pretending to do a build here'
}
}
stage('Windows') {
agent { label 'windows' }
steps {
unstash 'source'
echo 'Pretending to do a build here'
}
}
}
}
}
}
My understanding so far was that:
a change to the Jenkinsfile (not the whole repo) triggers the pipeline on any registered agent (or as configured in the pipeline project).
said agent (which is random) uses the pollSCM trigger in the Jenkinsfile to trigger the pipeline stages.
But where does the pollSCM trigger poll (what SCM repo)? And if it's a random agent then how can it reasonably detect changes across poll runs?
then the stages are being executed on the agents as allocated ...
Now I am confused what refers to what. So here my questions (all interrelated which is why I keep it together in one question):
The pipeline project polls the SCM just for the Jenkinsfile or for any changes? The repository in my case is the same (for Jenkinsfile and source files to build binaries from).
If the (project-level) polling triggers at any change rather than changes to the Jenkinsfile
Does the pollSCM trigger in the Jenkinsfile somehow automagically refer to the checkout step?
Then ... what would happen, would I have multiple checkout steps with differing settings?
What determines what repository (and what contents inside of that) gets polled?
... or is this akin to the checkout scm shorthand and pollSCM actually refers to the SCM configured in the pipeline project and so I can shorten the checkout() to checkout scm in the steps?
Unfortunately the user handbook didn't answer any of those questions and pollSCM has a total of four occurrences on a single page within the entire handbook.
I'll take a crack at this one:
The pipeline project polls the SCM just for the Jenkinsfile or for any
changes? The repository in my case is the same (for Jenkinsfile and
source files to build binaries from).
The pipeline project will poll the repo for ANY file changes, not just the Jenkinsfile. A Jenkinsfile in the source repo is common practice.
If the (project-level) polling triggers at any change rather than
changes to the Jenkinsfile Does the pollSCM trigger in the Jenkinsfile
somehow automagically refer to the checkout step?
Your pipeline will be executed when a change to the repo is seen, and the steps are run in the order that they appear in your Jenkinsfile.
Then ... what would happen, would I have multiple checkout steps with
differing settings?
If you defined multiple repos with the checkout step (using multiple checkout SCM calls) then the main pipeline project repo would be polled for any changes and the repos you define in the pipeline would be checked out regardless of whether they changed or not.
What determines what repository (and what contents inside of that)
gets polled? ... or is this akin to the checkout scm shorthand and
pollSCM actually refers to the SCM configured in the pipeline project
and so I can shorten the checkout() to checkout scm in the steps?
pollSCM refers to the pipeline project's repo. The entire repo is cloned unless the project is otherwise configured (shallow clone, lightweight checkout, etc.).
The trigger defined as pollSCM polls the source-control-management (SCM), at the repository and branch in which this jenkinsfile itself (and other code) is located.
For Pipelines which are integrated with a source such as GitHub or BitBucket, triggers may not be necessary as webhooks-based integration will likely already be present. The triggers currently available are cron, pollSCM and upstream.
It works for a multibranch-pipeline as trigger to execute the pipeline.
When Jenkins polls the SCM, exactly this repository and branch, and detects a change (i.e. new commit), then this Pipeline (defined in jenkinsfile) is executed.
Usually then the following SCM Step checkout will be executed, so that the specified project(s) can be built, tested and deployed.
See also:
SCM Poll in jenkins multibranch pipeline
SehllHacks(2020): Jenkins: Scan Multibranch Pipeline Without Build

Skipping stages in Jenkins pipeline on a Commit but not a PR

We are currently using the Jenkins/Groovy pipeline method for CI.
I'm trying to create a single pipeline for building packages and running unit tests on a branch (and let me know if this is bad practice).
The problem is on a commit I don't want to execute my test steps (due to the large number of commits and time to execute the full pipeline), but I still want the packaging stage to run for our manual testers to be able to pull and install on instances.
Is there any way to distinguish between a run for a PR vs a commit in the pipeline steps or in the job configuration?
Using the (assuming github, but theres bitbucket equiv as well)
https://wiki.jenkins.io/display/JENKINS/GitHub+Branch+Source+Plugin to discover Repositories to build branches and PR's will allow you to fall back on Jenkins ENV variables.
This allows simple if statement to determine if the build is for a branch, or for a PR, as PR's are built on a 'branch' of PR-n
Once a PR is open however, all commits would be built.
https://go.cloudbees.com/docs/cloudbees-documentation/cje-user-guide/index.html#github-branch-source
you can use the changeRequest built-in condition from Jenkins.
Executes the stage if the current build is for a "change request" (a.k.a. Pull Request on GitHub and Bitbucket, Merge Request on GitLab, Change in Gerrit, etc.). When no parameters are passed the stage runs on every change request, for example: when { changeRequest() }.
stage('Run only for pull requests to master branch or at the master branch') {
when {
anyOf {
branch 'master'
changeRequest target: 'master'
}
}
steps {
// this is a very long step for integration test that we don't want to execute often, but we need to execute before to merge to master
sh "${mvn} " +
"clean " +
"test-compile " +
"failsafe:integration-test failsafe:verify"
}
}

Resources