Skip to content

Commit

Permalink
updated pipeline script
Browse files Browse the repository at this point in the history
- added capability to sign all rpms builts by opflex build pipeline
  • Loading branch information
anmol372 committed Jul 29, 2024
1 parent cb6caa0 commit ad084f8
Show file tree
Hide file tree
Showing 3 changed files with 277 additions and 2 deletions.
101 changes: 101 additions & 0 deletions docker/rpms/my_setup_dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
set -a

# if dev=1, then we recompile tools before each invocation, even if binaries already exist (not recommended for signing users)
dev=0

# If you are running rpm signing tools from a daemon process, set the Environment Variable RPM_SIGN_DAEMON=1, otherwise leave it unset.
# This will prevent output to a tty, which doesn't exist on a daemon process
#RPM_SIGN_DAEMON=1

## Use ./signContent-swims for SWIMS
signing_helper=./signContent-swims

key_creation_time=0 # If set to 1, a timestamp of current time will be added to the signature in the public key file, otherwise
# a static timestamp of "2017-Jan-01" will be used (when set to 0)

sig_creation_time=0 # If set to 0, or not set, a timestamp of current time will be added to the signature file (common case).
# If set to 1, a static timestamp (of 2017-Jan-02) will be added to the signature file. This
# aligns with the 'key_creation_time' timestamp setting above, the key must be equal to or of older age than the
# signature to verify successfully.
# If set to > 0, it is assumed to be seconds since the epoch, 1970-01-01 00:00:00 UTC
# This value can typically be determined using the date unix command for a particular date, e.g.
# $ date --date='2018-01-01' +%s
# 1514782800
#
# $ date --date='2021-07-11 11:43:40' +%s
# 1626018220


## comment these out to use the production SWIMS server
#swims_certfile= # if set, alternate cert to validate host, typically don't use
#swims_host='swims-stg-aln.cisco.com' # if set, alternate host to use

swims_client_log="swims_client.log"

#For the swims_client command, you have options:
# 1) For newer 64-bit machines (e.g. RHEL7, RHEL8, Ubuntu16, ubuntu18, Ubuntu20, and future), use the code_sign7.x86_64 executable provided in this repo (built on py3 RHEL7)
# 2) For python2 and/or older 64-bit machines (e.g. CentOs6, CEL6, etc), use the code_sign.x86_64 executable provided in this repo
# 3) For 32-bit machines, use the code_sign6_32 executable provided in this repo
# 4) Use your own code_sign executable copy (not recommended), provide the path to it
# 5) A copy of the swims_client.py script (see below)

#This example uses option 1, always include the keyword 'swims' (except for option 5)
swims_client_cmd=$1' swims'
#swims_client_cmd="$PWD"'/code_sign.x86_64 swims'

## un-comment this to use option 5, a swims_client.py python script (not provided in repo)
##swims_client_cmd='python swims_client.py' # eval-able string

sig_type=dev # must be either "dev" or "rel"
#gpgkeydir=<path to the directory to store/retrieve the gpg key> # if you want to create the gpgkey (i.e. run-make-cert) into or retrieve the gpgkey from someplace other than
# this scripts directory, set this parameter to the directory path only. Otherwise don't set. Include final
# slash if you do set it, e.g. /tmp/ . The keys must be named rel.gpg or dev.gpg regardless.

user1=$2 # CEC name; only user required for dev signatures
pass1=push # For DUO push request

notes="RPM Test for ISC"

#Generic userid can be used for DEV signing
#generic_user= # generic user id
#generic_pw= # generic user password

# To use tickets rather than OTP (for SWIMS), specify the ticket_file path
# e.g. ticket_file=/home/swims/RPM/rpm_deb_signing-master/Linux-64/swims-openpgp/myticket
#ticket_file=<path to ticket> # if this is specified, use a ticket rather than OTP (for SWIMS)
#ticket_file=/home/swims/repo-rpm-deb-sign-src/rpm_deb_sign_src/Linux-64/swims-openpgp/mph-2987471-DEV-ticket

# To use session tokens, use the SWIMS_SESSION_TOKEN and SWIMS_TREAT_TICKET_AS_TOKEN Environment Variables. See
# https://docs.cisco.com/share/page/site/nextgen-edcs/document-details?nodeRef=workspace://SpacesStore/44769d41-9bb4-4a4e-b6c1-cbfd1a7184a1 for more details.

# If using a token, "SWIMS_SESSION_TOKEN" must be set to the raw token string or the path to the file containing the token.
#SWIMS_SESSION_TOKEN=/tmp/build-session.tkn
# If using a token for a legacy build script that cannot easily utilize the "SWIMS_SESSION_TOKEN" variable,
# the "ticket_file" variable must be set to the path to the file containing the token,
# and "SWIMS_TREAT_TICKET_AS_TOKEN" must be set to "True."
#SWIMS_TREAT_TICKET_AS_TOKEN=True

# User provided encoded JSON string or file path to the file containing the encoded JSON string that includes
# all mandatory and optional build or artifact metadata regarding the build session. (See code_sign tool: "code_sign build-data -h")
#BUILD_METADATA=
#ARTIFACT_METADATA=

product=dcn-container-vm-plugins # Product name (also key name for Abraxas, which only has one key for product)
product_key=dcn-container-vm-keys-dev # Key name for SWIMS (defaults to product name if not given)
#product_pid=testPid # PID for SWIMS; if commented out, no PID will be given. If your PID is not marked as 'Real Pid' in your Product Entry in SWIMs, don't set this.

#armored_pgp_sig=yes # Uncomment to make run-extsign produce an armored base64 gpg signature file

#If you are using GRUB2 to verify gpg signatures for files (e.g. the kernel), then the file must be signed with RPM_MAJOR_VERSION = 5. This allows the key id to be placed
#in the unhashed sub-components within the signature, which GRUB2 currently expects.
#RPM_MAJOR_VERSION = 5

## Customer-visible identity for "who signed this code?"
# Do not include invalid characters like '\x00', '(', ')', '<' and '>' in <identity_*> fields
identity_name=$2
identity_email=$2'@cisco.com'
#identity_comment="${product}.${sig_type}" # if commented out / undefined, default will be built per this pattern

set +a

# vim: filetype=sh
132 changes: 132 additions & 0 deletions docker/rpms/sign-rpm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/bin/bash

set -x
#TODO: add verification
#TODO: add release signing

# Ensure the script is called with the correct number of arguments
if [ "$#" -ne 4 ]; then
#echo "Usage: <rpm_path> <base64_vault_role> <base64_vault_sec> <build_user1> <build_user2>"
exit 1
fi

# Define the RPM directories
RPM_DIR_PATH=$(find "$1" -type d -name "*opflexrpms*" | grep "${BUILD_NUMBER}")
#RPM_DIR_PATH=$(find "$1" -type d -name "*opflexrpms*" | grep "19")
if [ -z "$RPM_DIR_PATH" ]; then
echo "No RPM directory found for build number ${BUILD_NUMBER}"
exit 1
fi
#NOARCH_DIR="$RPM_DIR/RPMS/noarch"
#SRPMS_DIR="$RPM_DIR/SRPMS"

# Setup Vault
VAULT_ADDR="https://keeper.cisco.com"
VAULT_NAMESPACE="swims-prod/GROUP_2"
VAULT_ROLE_ID=$KEEPER_ROLE_ID
VAULT_SECRET_ID=$KEEPER_SECRET

# Signing CECs
USER1=$2
USER2=$3
# Release Signing or not
RELEASE=$4
# Constants from Travis CI environment variables
BRANCH_NAME=$GIT_BRANCH
PROJECT_NAME=$GIT_URL

# Variables
REPO_URL="https://wwwin-github.cisco.com/STO-Image-Signing/rpm_deb_signing.git"
SIGNHELPER_DIR="$WORKSPACE/rpmbuild"
RPM_DEB_SIGN="$WORKSPACE/rpmbuild/rpm_deb_signing"
CODE_SIGN_EXEC="$RPM_DEB_SIGN/Linux-64/swims-openpgp/code_sign.x86_64"
RPM_SIGN_SCRIPTDIR="$RPM_DEB_SIGN/Linux-64/swims-openpgp"
RPM_BATCH_SIGN="$RPM_SIGN_SCRIPTDIR/rpm_sign_batchmode.py3"
RUN_EXT_SIGN="$RPM_SIGN_SCRIPTDIR/run-extsign"
RPMMACROS="$WORKSPACE/signedRPMS"

WORKING_DIR="$WORKSPACE/SIGNRPMS"
OUTPUT_TOKEN="$WORKING_DIR/dcn-bld.tkn"
LOG_FILE="$WORKING_DIR/swims-session-token.log"

PAYLOAD_OUTPUT="$WORKING_DIR/requestPayload.out3"
SIGNATURE_OUTPUT="$WORKING_DIR/requestPayload.sig3"
SESSION_TOKEN_OUTPUT="$WORKING_DIR/build-session.tkn"

REASON="CLI Test #1"
BUILD_INITIATOR=$USER1
BUILD_TYPE="DEV"
ATTESTATION_KEY_NAME="dcn-plugin-build"
PRODUCT="dcn-container-vm-plugins"
AUTH_TYPE="OTP"
USERNAME=$USER1
PASSWORD="push"

# Step 0: Clone the repository if it does not exist and navigate into it
mkdir -p $SIGNHELPER_DIR
rm -rf $RPM_DEB_SIGN
git clone $REPO_URL $RPM_DEB_SIGN

mkdir -p $WORKING_DIR

# Find RPM files in the RPM directory
RPM_FILES=$(find "$RPM_DIR_PATH" -type f -name "*.rpm")

if [ -z "$RPM_FILES" ]; then
echo "No RPM files found to sign in $RPM_DIR_PATH"
exit 1
fi

# Define the CSV file path
CSV_FILE="$SIGNHELPER_DIR/rpm_files.csv"
# Ensure csv is empty
> "$CSV_FILE"
# Append RPM file paths to the CSV file
for RPM_FILE in $RPM_FILES; do
echo "$RPM_FILE" >> "$CSV_FILE"
done

# Step 1: Create build authorization token
$CODE_SIGN_EXEC swims build authorization create -product $PRODUCT -buildType $BUILD_TYPE \
-attestationKeyName $ATTESTATION_KEY_NAME -reason "$REASON" -buildInitiators $BUILD_INITIATOR \
-authType $AUTH_TYPE -username1 $USERNAME -password1 $PASSWORD -out $OUTPUT_TOKEN -logFile $LOG_FILE

# Step 2: Encode payload for build session
$CODE_SIGN_EXEC swims build session encodePayload -buildInitiator $BUILD_INITIATOR -branchName $BRANCH_NAME \
-projectName $PROJECT_NAME -buildAuthToken $OUTPUT_TOKEN -out $PAYLOAD_OUTPUT -logFile $LOG_FILE

# Step 3: Set Vault environment variables
export VAULT_ADDR=$VAULT_ADDR
export VAULT_NAMESPACE=$VAULT_NAMESPACE
export VAULT_ROLE_ID=$VAULT_ROLE_ID
export VAULT_SECRET_ID=$VAULT_SECRET_ID

# Step 4: Sign the payload with attestation key
$CODE_SIGN_EXEC swims utils vault signWithAttestationKey -attestationKeyName $ATTESTATION_KEY_NAME \
-input $PAYLOAD_OUTPUT -out $SIGNATURE_OUTPUT -logFile $LOG_FILE

# Step 5: Create build session token
$CODE_SIGN_EXEC swims build session create -requestPayload $PAYLOAD_OUTPUT -requestSignature $SIGNATURE_OUTPUT \
-out $SESSION_TOKEN_OUTPUT -logFile $LOG_FILE

# Print completion message
echo "Build session token created successfully and stored in $SESSION_TOKEN_OUTPUT"

export SWIMS_SESSION_TOKEN=$SESSION_TOKEN_OUTPUT
source $WORKSPACE/docker/rpms/my_setup_dev.sh $CODE_SIGN_EXEC $USER1
cd $RPM_SIGN_SCRIPTDIR
./run-make-cert.exp
gpg --import dev.gpg
#gpg --list-keys

# Create the ~/.rpmmacros file with the specified configuration
cat >"$WORKING_DIR/.rpmmacros" <<EOF
%_gpg_name _
%__gpg_check_password_cmd /bin/true
%__gpg_sign_cmd $RUN_EXT_SIGN \\
run-extsign %{__plaintext_filename} %{__signature_filename}
EOF

python3 $RPM_BATCH_SIGN -f $CSV_FILE -m $WORKING_DIR/.rpmmacros

#rm -rf $WORKING_DIR
46 changes: 44 additions & 2 deletions pipeline-rpm-script
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ pipeline {
DOCKER_TAG = 'latest'
BASEIMAGE = 'noiro/opflex-rpm-build-base:master-test'
BRANCH = 'master'
RPM_DIR = "$WORKSPACE/docker/rpms"
SIGNED_RPMS = "$WORKSPACE/rpmbuild/RPMS/noarch"
}
stages {
stage('Main Script') {
stage('Build Opflex RPMS') {
steps {
script {
sh """
Expand All @@ -18,5 +20,45 @@ pipeline {
}
}
}
stage('Extract RPM Tar File') {
steps {
script {
def tarFile = "opflexrpms-${BUILD_NUMBER}.tar.gz"
sh """
rm -rf ${SIGNED_RPMS}
mkdir -p ${SIGNED_RPMS}
tar -xf ${RPM_DIR}/${tarFile} -C ${SIGNED_RPMS}
"""
}
}
}
stage('Sign RPM') {
steps {
withCredentials([
conjurSecretCredential(credentialsId: 'noiro-conjur-keeper-role-id', variable: 'KEEPER_ROLE_ID'),
conjurSecretCredential(credentialsId: 'noiro-conjur-keeper-secret-id', variable: 'KEEPER_SECRET')
]) {
script {
// Handle empty params.SIGNUSER2 and pass empty string if it is
def signUser2 = params.SIGNUSER2 ?: 'empty'
// Execute sign-rpm.sh with Vault credentials passed as parameters
sh """
./docker/rpms/sign-rpm.sh ${SIGNED_RPMS} ${params.SIGNUSER1} ${signUser2} ${params.ReleaseBuild}
"""
}
}
}
}
stage('Re-Tar Signed RPMs') {
steps {
script {
def tarFile = "signed-opflexrpms-${BUILD_NUMBER}.tar.gz"
sh """
cd ${SIGNED_RPMS}
tar -czf ${SIGNED_RPMS}/${tarFile} *
"""
}
}
}
}
}
}

0 comments on commit ad084f8

Please sign in to comment.