How To: Use credentials from CyberArk

How To: Use credentials from CyberArk

Some of our customers use CyberArk as their enterprise password store.  Datical's "hammer" commands are able to read credentials from environment variables so we need a way to get the credentials out of CyberArk and into the environment so that Datical can use them.

In this example, we will assume that the customer is storing database credentials (username and password) in CyberArk. We know the database name, but need the userid and password to access that database.



Setting up an account in CyberArk

  1. In CyberArk UI, on the Accounts page click "Add Account"




  2. Choose "Database"

  3. We'll use Oracle for this example

  4. Next, choose the safe you want to store the creds in.  We will store them in the "test" safe




  5. Fill out the Username, Password, and Confirm fields. 
    Note that I also added the string "gambit_ora_ref" in the Address field although it's optional.  This is for visibility in the list view which we'll see in just a minute
    Also select the option to "Customize Account Name" so that you can assign a meaningful name to this account. I set it to "gambit_ora_ref"




  6. Scroll down and fill in the database name. Mine is "REF_DB" since that is what I called the Oracle database in the pipeline.  It is not used as part of this API reference though.




  7. Click "ADD" and you should get a success message:  (If you go back and edit you will see save vs add button)

  8. When the account shows up in the list view you're done setting up the account




Retrieving credentials from CyberArk via a REST call

  1. There are a few values that are going to be needed for each API call

    1. BaseURL

    2. Port number (e.g., 8080)

    3. AppID (e.g., Datical)

    4. SafeName is Test (This is what you chose in step 4 above)

    5. Folder is root 

  2. Create an http GET call using the above values and the following format template:
    {{BaseURL}}:{{Port}}/AIMWebService/api/Accounts?AppID={{AppID}}&Safe={{SafeName}}&Folder={{Folder}}&Object={{ObjectName}}
    API is documented here -> https://documenter.getpostman.com/view/998920/RzZ9Gz1U?bs=true&version=latest#97bada25-0588-4660-9fc3-bae9f1087596

  3. In the above template, {{ObjectName}} will be the value you set for the "Account Name" in step 5 of Setting up an account in CyberArk above


  4. My resulting URL for this example will look like this:
    http://services-uswest.skytap.com:8080/AIMWebService/api/Accounts?AppID=Datical&Safe=Test&Folder=root&Object=gambit_ora_ref


  5. When I drop that in a browser address bar the server will respond with the following json object:

    JSON Response from CyberArk REST call

    { "Content":"password", "CreationMethod":"PVWA", "Address":"gambit_ora_ref", "Safe":"Test", "UserName":"GAMBITCARD_REF_DB", "Database":"REF_DB", "PolicyID":"Oracle", "DeviceType":"Database", "Name":"gambit_ora_ref", "Folder":"Root", "PasswordChangeInProcess":"False" }
  6. The password is returned in the "Content" attribute


  7. Use the instructions in Provide Runtime Credentials to set the necessary runtime database credentials.

  8. Here is an example Jenkinsfile script that I used to incorporate the credentials (lines 32-36).  (I used JsonSlurper to parse the JSON response from CyberArk)

    Jenkinsfile

    import groovy.json.JsonSlurper node { try { // Environment Variables env.appname = "GambitCard" env.scmCreds = "e0de9ac3-3636-48d7-b95e-35443ab32b53" env.scmType = "git" env.ddbURL = "ssh://jenkins@win-20e107kb4tn:7999/gc/gambitcard.git" env.srcURL = "ssh://jenkins@win-20e107kb4tn:7999/gc/gambitcardsql.git" // Pad env.BUILD_NUMBER so fetching LATEST will work properly on Artifactory and Xebia XLD // Requires https://wiki.jenkins.io/display/JENKINS/Permissive+Script+Security+Plugin env.BUILD_NUMBER = "${env.BUILD_NUMBER}".padLeft(4,'0') //MOVED TO JENKINS NODE SETTINGS //env.DATICAL_CLIENT_SECRET="123abc" //env.DATICAL_SERVER="hostname" //env.curlHome = "C:\\apps\\Git\\mingw64\\bin" //env.datHome = "C:\\apps\\DaticalDB\\repl" //env.mvnHome = "C:\\apps\\apache-maven-3.3.9\\bin" //env.ucdHome = "C:\\apps\\ibm-ucd-agent\\opt\\udclient" //env.ZipHome = "C:\\apps\\7-Zip" // Print Environment Variables //echo sh(returnStdout: true, script: 'env') // String Definitions //def appname = "${env.appname}" deleteDir() stage('Get CYBERARKCREDS') { URL apiURL = "http://services-uscentral.skytap.com:14200/AIMWebService/api/Accounts?AppID=Datical&Safe=Test&Folder=root&Object=gambit_ora_ref".toURL() Map myjson = new JsonSlurper().parse(apiURL.newReader()) env.DDB_USER = myjson.UserName env.DDB_PASS = myjson.Content println("${env.DDB_USER}") } stage('Source Checkout') { if (env.scmType == 'git') { parallel ( CheckoutDDB: { checkout([$class: "GitSCM", branches: [[name: "*/master"]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: "RelativeTargetDirectory", relativeTargetDir: "ddb"], [$class: "LocalBranch", localBranch: "master"], [$class: "UserIdentity", email: "jenkins@company.com", name: "jenkins"]], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${env.scmCreds}", url: "${env.ddbURL}"]]]) }, CheckoutAPP: { checkout([$class: "GitSCM", branches: [[name: "*/${env.pipeline}"]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: "RelativeTargetDirectory", relativeTargetDir: "src"], [$class: "LocalBranch", localBranch: "${env.pipeline}"], [$class: "UserIdentity", email: "jenkins@company.com", name: "jenkins"]], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${env.scmCreds}", url: "${env.srcURL}"]]]) } ) } if (env.scmType == 'svn') { parallel ( CheckoutDDB: { checkout changelog: false, poll: false, scm: [$class: "SubversionSCM", additionalCredentials: [], excludedCommitMessages: "", excludedRegions: "", excludedRevprop: "", excludedUsers: "", filterChangelog: false, ignoreDirPropChanges: false, includedRegions: "", locations: [[credentialsId: "7545c833-66a0-4386-8a16-9d8a51c98449", depthOption: "infinity", ignoreExternalsOption: true, local: "ddb", remote: "${env.ddbURL}"], [credentialsId: "7545c833-66a0-4386-8a16-9d8a51c98449", depthOption: "infinity", ignoreExternalsOption: true, local: "ddb", remote: "${env.ddbURL}"]], workspaceUpdater: [$class: "UpdateUpdater"]] }, CheckoutAPP: { checkout changelog: false, poll: false, scm: [$class: "SubversionSCM", additionalCredentials: [], excludedCommitMessages: "", excludedRegions: "", excludedRevprop: "", excludedUsers: "", filterChangelog: false, ignoreDirPropChanges: false, includedRegions: "", locations: [[credentialsId: "7545c833-66a0-4386-8a16-9d8a51c98449", depthOption: "infinity", ignoreExternalsOption: true, local: "src", remote: "${env.srcURL}"], [credentialsId: "7545c833-66a0-4386-8a16-9d8a51c98449", depthOption: "infinity", ignoreExternalsOption: true, local: "src", remote: "${env.srcURL}"]], workspaceUpdater: [$class: "UpdateUpdater"]] } ) } } stage('PackageDB') { // Set Upstream Branches for Git if (env.scmType == 'git') { bat 'cd src && git branch --set-upstream-to=origin/%pipeline% %pipeline%' bat 'cd ddb && git branch --set-upstream-to=origin/master master' } // Show Hammer Version Details //bat 'hammer.bat show version' // Set Version if (env.pipeline == 'pipeline1') { env.version = "2.0.${env.BUILD_NUMBER}" } if (env.pipeline == 'pipeline2') { env.version = "3.0.${env.BUILD_NUMBER}" } if (env.pipeline == 'hotfix') { //ASSUME YOU ARE HOTFIXING CURRENT VERSION env.version = "1.0.${env.BUILD_NUMBER}_HOTFIX" } //Check creds println('USER') println("${env.DDB_USER}") // Invoke Datical Database Code Packager //withCredentials([usernamePassword(credentialsId: 'DATICAL5', usernameVariable: 'DATICAL_USERNAME', passwordVariable: 'DATICAL_PASSWORD')]) { //bat 'cd ddb && hammer.bat groovy deployPackager.groovy %pipeline% scm=true labels=%BUILD_TAG%' bat 'cd ddb && hammer.bat groovy deployPackager.groovy pipeline=%pipeline% scm=true labels=%version%' //} // Create Datical Artifact bat 'cd ddb && 7za.exe a -tzip -x!.git -x!.svn -x!Logs -x!Reports -x!Snapshots -x!Profiles -x!.classpath -x!.gitignore -x!.metadata -x!.project -x!.reporttemplates -x!daticaldb.log -x!deployPackager.properties -x!svn-ignore.properties ..\\%appname%DB.zip' } stage('BuildApp') { bat 'sed -i s/VERSION_NO/%version%/g .\\src\\app_code\\src\\main\\webapp\\index.jsp' bat 'cd src\\app_code && mvn package' bat 'move src\\app_code\\target\\%appname%-1.0-SNAPSHOT.war .\\%appname%.war' } stage('Package Artifact') { if (env.CDTool != 'UCD') { // Artifactory Configuration def server = Artifactory.server 'art-001' def buildInfo = Artifactory.newBuildInfo() // Set custom build name and number. buildInfo.setName "${env.appname}" buildInfo.setNumber "${env.version}" def uploadSpec = """ { "files": [ { "pattern": "*zip", "target": "${env.appname}/${env.appname}DB-${env.version}.zip", "props": "pipeline=${env.pipeline}" }, { "pattern": "*war", "target": "${env.appname}/${env.appname}-${env.version}.war", "props": "pipeline=${env.pipeline}" } ] }""" // Upload to Artifactory. server.upload spec: uploadSpec, buildInfo: buildInfo // Publish build info. server.publishBuildInfo buildInfo if (env.CDTool == 'XLD') { // used to create and publish the artifacts in XLD xldCreatePackage artifactsPath: ".", manifestPath:"src/deployit-manifest.xml", darPath: '${appname}-${version}.dar' xldPublishPackage serverCredentials: 'Admin', darPath: '${appname}-${version}.dar' //xldCreatePackage artifactsPath: ".", manifestPath:"src/sql_code/deployit-manifest_ddb.xml", darPath: '${appname}_ddb-${version}.dar' //xldPublishPackage serverCredentials: 'Admin', darPath: '${appname}_ddb-${version}.dar' } } if (env.CDTool == 'UCD') { // Add UCD Component Version bat 'udclient.cmd -username admin -password password -weburl https://win-20e107kb4tn:8444 createVersion -component %appname%-DB -name %version%' bat 'udclient.cmd -username admin -password password -weburl https://win-20e107kb4tn:8444 createVersion -component %appname%-WAR -name %version%' // Add Files to new Component Version bat 'udclient.cmd -username admin -password password -weburl https://win-20e107kb4tn:8444 addVersionFiles -component %appname%-DB -version %version% -base %WORKSPACE% -include **/%appname%*.zip' bat 'udclient.cmd -username admin -password password -weburl https://win-20e107kb4tn:8444 addVersionFiles -component %appname%-WAR -version %version% -base %WORKSPACE% -include **/%appname%*.war' } } if (env.pipeline != 'hotfix') { stage('Deploy To DEV') { env.deployenv = "DEV" parallel( DeployApp: { if (env.pipeline == 'pipeline1') { env.deployenv = "DEV" } if (env.pipeline == 'pipeline2') { env.deployenv = "DEV2" } build job: String.valueOf(appname) + '-DEP', parameters: [ string(name: 'pipeline', value: String.valueOf("${env.pipeline}")), string(name: 'labels', value: String.valueOf("${env.pipeline}")), string(name: 'deployenv', value: String.valueOf("${env.deployenv}")), string(name: 'deployver', value: String.valueOf("${env.version}")), string(name: 'CDTool', value: String.valueOf("${env.CDTool}")) ] }, DeployDB: { //xldDeploy serverCredentials: 'Admin', environmentId: 'Environments/${deployenv} ENV', packageId: 'Applications/${env.appname}_ddb/${version}' //Refresh Pipeline for DMC Status //bat 'cd ddb && hammer.bat status' //withCredentials([usernamePassword(credentialsId: 'DATICAL5', usernameVariable: 'DATICAL_USERNAME', passwordVariable: 'DATICAL_PASSWORD')]) { // bat 'cd ddb && hammer.bat status %appname%' //} } ) } stage('Promotion Approval') { echo 'wait for approval' } input 'Continue to Deploy TEST' stage('Deploy To TEST') { env.deployenv = "TEST" parallel( DeployApp: { if (env.pipeline == 'pipeline1') { env.deployenv = "TEST" } if (env.pipeline == 'pipeline2') { env.deployenv = "TEST2" } build job: String.valueOf(appname) + '-DEP', parameters: [ string(name: 'pipeline', value: String.valueOf("${env.pipeline}")), string(name: 'labels', value: String.valueOf("${env.pipeline}")), string(name: 'deployenv', value: String.valueOf("${env.deployenv}")), string(name: 'deployver', value: String.valueOf("${env.version}")), string(name: 'CDTool', value: String.valueOf("${env.CDTool}")) ] }, DeployDB: { //xldDeploy serverCredentials: 'Admin', environmentId: 'Environments/${deployenv} ENV', packageId: 'Applications/${env.appname}_ddb/${version}' sleep 15 } ) } } stage('Promotion Approval') { echo 'wait for approval' } input 'Continue to Deploy PROD' stage('Deploy To PROD') { env.deployenv = "PROD" parallel( DeployApp: { build job: String.valueOf(appname) + '-DEP', parameters: [ string(name: 'pipeline', value: String.valueOf("${env.pipeline}")), string(name: 'labels', value: String.valueOf("${env.pipeline}")), string(name: 'deployenv', value: String.valueOf("${env.deployenv}")), string(name: 'deployver', value: String.valueOf("${env.version}")), string(name: 'CDTool', value: String.valueOf("${env.CDTool}")) ] }, DeployDB: { if (env.pipeline == 'hotfix') { //withCredentials([usernamePassword(credentialsId: 'DATICAL5', usernameVariable: 'DATICAL_USERNAME', passwordVariable: 'DATICAL_PASSWORD')]) { //bat 'cd ddb\\%appname% && hammer.bat status %appname%' //} } } ) } } catch (e) { // If there was an exception thrown, the build failed currentBuild.result = "FAILED" throw e } finally { // Success or failure, always send notifications notifyBuild(currentBuild.result) archiveArtifacts allowEmptyArchive: true, artifacts: '**/ddb/**/Reports/**' } } def notifyBuild(String buildStatus = 'STARTED') { // build status of null means successful buildStatus = buildStatus ?: 'SUCCESSFUL' def subject = "${buildStatus}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'" //def summary = "${subject} (${env.BUILD_URL})" def summary = "${subject} (http://win-20e107kb4tn:8080/blue/organizations/jenkins/${env.JOB_NAME}/detail/${env.JOB_NAME}/${env.BUILD_NUMBER}/pipeline)" // Send notifications mail bcc: '', body: summary, cc: '', from: 'jenkins@company.local', replyTo: '', subject: subject, to: 'dev@company.local' }





Copyright © Datical 2012-2020 - Proprietary and Confidential