Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 50 additions & 5 deletions .ci/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
pipeline {
agent { label 'ubuntu-18 && immutable' }
environment {
REPO = "elastic-package"

BASE_DIR="src/github.com/elastic/elastic-package"
JOB_GIT_CREDENTIALS = "f6c7695a-671e-4f4f-a331-acdce44ff9ba"
GITHUB_TOKEN_CREDENTIALS = "2a9602aa-ab9f-4e52-baf3-b71ca88469c7"
Expand All @@ -16,6 +18,16 @@ pipeline {
JOB_GCS_BUCKET = 'beats-ci-temp'
JOB_GCS_CREDENTIALS = 'beats-ci-gcs-plugin'
JOB_GCS_EXT_CREDENTIALS = 'beats-ci-gcs-plugin-file-credentials'
JOB_SIGNING_CREDENTIALS = 'sign-artifacts-with-gpg-job'
INTERNAL_CI_JOB_GCS_CREDENTIALS = 'internal-ci-gcs-plugin'

INFRA_SIGNING_BUCKET_NAME = 'internal-ci-artifacts'
INFRA_SIGNING_BUCKET_ARTIFACTS_SUBFOLDER = "${env.REPO}/${env.BUILD_TAG}"
INFRA_SIGNING_BUCKET_SIGNED_ARTIFACTS_SUBFOLDER = "${env.INFRA_SIGNING_BUCKET_ARTIFACTS_SUBFOLDER}/signed-artifacts"
INFRA_SIGNING_BUCKET_ARTIFACTS_PATH = "gs://${env.INFRA_SIGNING_BUCKET_NAME}/${env.INFRA_SIGNING_BUCKET_ARTIFACTS_SUBFOLDER}"
INFRA_SIGNING_BUCKET_SIGNED_ARTIFACTS_PATH = "gs://${env.INFRA_SIGNING_BUCKET_NAME}/${env.INFRA_SIGNING_BUCKET_SIGNED_ARTIFACTS_SUBFOLDER}"

INTEGRATIONS_SIGNATURES_PATH = 'build/integrations-elastic-signatures' // different path not to override signatures archived in the "build-zip" step
}
options {
timeout(time: 1, unit: 'HOURS')
Expand Down Expand Up @@ -74,9 +86,7 @@ pipeline {
always {
dir("${BASE_DIR}") {
archiveArtifacts(allowEmptyArchive: true, artifacts: 'build/test-results/*.xml')
junit(allowEmptyResults: false,
keepLongStdio: true,
testResults: "build/test-results/*.xml")
junit(allowEmptyResults: false, keepLongStdio: true, testResults: "build/test-results/*.xml")
stashCoverageReport()
}
}
Expand All @@ -99,7 +109,8 @@ pipeline {
'check-packages-with-kind': generateTestCommandStage(command: 'test-check-packages-with-kind', artifacts: ['build/test-results/*.xml', 'build/kubectl-dump.txt', 'build/elastic-stack-dump/check-*/logs/*.log', 'build/elastic-stack-dump/check-*/logs/fleet-server-internal/*'], junitArtifacts: true, publishCoverage: true),
'check-packages-other': generateTestCommandStage(command: 'test-check-packages-other', artifacts: ['build/test-results/*.xml', 'build/elastic-stack-dump/check-*/logs/*.log', 'build/elastic-stack-dump/check-*/logs/fleet-server-internal/*'], junitArtifacts: true, publishCoverage: true),
'build-zip': generateTestCommandStage(command: 'test-build-zip', artifacts: ['build/elastic-stack-dump/build-zip/logs/*.log', 'build/integrations/*.sig']),
'profiles-command': generateTestCommandStage(command: 'test-profiles-command')
'profiles-command': generateTestCommandStage(command: 'test-profiles-command'),
'sign-with-elastic': generateTestSignWithElasticStage()
]

def checkSinglePackageTasks = generateTestCheckSinglePackageStage(artifacts: ['build/test-results/*.xml', 'build/elastic-stack-dump/check-*/logs/*.log', 'build/elastic-stack-dump/check-*/logs/fleet-server-internal/*'], junitArtifacts: true, publishCoverage: true)
Expand Down Expand Up @@ -144,6 +155,40 @@ def cleanup(){
unstash 'source'
}

def generateTestSignWithElasticStage() {
return {
withNode(labels: "ubuntu-20 && immutable", sleepMax: 20, forceWorkspace: true) {
cleanup()
dir("${BASE_DIR}"){
withMageEnv(){
sh(label: 'Install elastic-package',script: "make install")
sh(label: 'Prepare for tests (build zipped packages)',script: "make build-unsigned-zip-for-tests")
googleStorageUpload(bucket: env.INFRA_SIGNING_BUCKET_ARTIFACTS_PATH,
credentialsId: env.INTERNAL_CI_JOB_GCS_CREDENTIALS,
pathPrefix: 'build/integrations/',
pattern: 'build/integrations/*.zip',
sharedPublicly: false,
showInline: true)
withCredentials([string(credentialsId: env.JOB_SIGNING_CREDENTIALS, variable: 'TOKEN')]) {
triggerRemoteJob(auth: CredentialsAuth(credentials: 'local-readonly-api-token'),
job: 'https://internal-ci.elastic.co/job/elastic+unified-release+master+sign-artifacts-with-gpg',
token: TOKEN,
parameters: "gcs_input_path=${env.INFRA_SIGNING_BUCKET_ARTIFACTS_PATH}",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, does this job check that this path belongs to elastic? In case somehow a malicious pipeline triggers this job to sign anything placed in a bucket with public access.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The job is configured in the internal-ci instance, so the malicious user should be also internal?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering more about a change in the Jenkinsfile in a PR.

useCrumbCache: true,
useJobInfoCache: true)
}
googleStorageDownload(bucketUri: "${env.INFRA_SIGNING_BUCKET_SIGNED_ARTIFACTS_PATH}/*",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this downloading all the packages ever signed? Or there is some cleanup process for the signed artifacts path?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be ownest with you I have never tried downloading everything in that bucket as it could kill the CI worker :D It's the same job we're using to sign Beats artifacts.

credentialsId: env.INTERNAL_CI_JOB_GCS_CREDENTIALS,
localDirectory: "${env.INTEGRATIONS_SIGNATURES_PATH}/",
pathPrefix: "${env.INFRA_SIGNING_BUCKET_SIGNED_ARTIFACTS_SUBFOLDER}")
sh(label: 'Rename .asc to .sig', script: 'for f in ' + "${env.INTEGRATIONS_SIGNATURES_PATH}" + '/*.asc; do mv "$f" "${f%.asc}.sig"; done')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be nice to encapsulate these steps of uploading, signing, downloading and renaming into a single signArtifacts helper 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they will be encapsulated. I'm planning to wrap (signing + push to Package Storage) into a single command. I have to make sure the push works correctly.

archiveArtifacts(artifacts: "${env.INTEGRATIONS_SIGNATURES_PATH}/*.sig")
}
}
}
}
}

def generateTestCheckSinglePackageStage(Map args = [:]) {
def artifacts = args.get('artifacts') ? args.get('artifacts') : []
def junitArtifacts = args.get('junitArtifacts') ? args.get('junitArtifacts') : false
Expand Down Expand Up @@ -293,4 +338,4 @@ def withCloudTestEnv(Closure body) {
withEnvMask(vars: maskedVars) {
body()
}
}
}
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ test-profiles-command:

test: test-go test-stack-command test-check-packages test-profiles-command test-build-zip

build-unsigned-zip-for-tests:
./scripts/build-unsigned-zip.sh

check-git-clean:
git update-index --really-refresh
git diff-index --quiet HEAD
Expand Down
14 changes: 14 additions & 0 deletions scripts/build-unsigned-zip.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

set -euxo pipefail

OLDPWD=$PWD

# Build packages
for d in test/packages/*/*/; do
(
cd $d
elastic-package build --zip -v
)
done
cd -