Jenkins credentials - how to pass into Fastlane? - jenkins

I have a secret file in Jenkins Credentials. And I am trying to use it as an environment variable to use later in Fastlane script. But inside the Fastlane script I am getting only ****. How can I get the secret key in Fastlane from Jenkins?
Piece of Jenkins Groovy file:
pipeline {
agent any
environment {
APP_STORE_KEY = credentials('ASC_KEY')
#...
}
#...
stage('Upload to TestFlight') {
steps {
sh "bundle exec fastlane deploy --env $APP_ENV"
}
}
}
Piece of Fastfile:
lane :deploy do
api_key = app_store_connect_api_key(
key_id: ENV['ASCAPI_KEY_ID'],
issuer_id: ENV['ASCAPI_ISSUER_ID'],
key_content: ENV['APP_STORE_KEY']
)
pilot(
username: ENV['APPLE_ID'],
app_identifier: ENV['APP_BUNDLE_IDENTIFIER'],
dev_portal_team_id: ENV['TEAM_ID'],
team_id: ENV['TEAM_ID'],
api_key: api_key,
app_platform: "ios",
ipa: ENV['OUTPUT_IPA_NAME'],
skip_waiting_for_build_processing: true
)
end
I've tried to print APP_STORE_KEY with puts(ENV['APP_STORE_KEY']) in Fastfile and it returns ****.
Maybe you know some workaround or a better way to do this.

I've managed it to work. it works perfectly with the base64 encoded content of .p8 file.
First of all we need to get base64 encoded string from .p8 file. and copy the result. Then in Jenkins Credentials create a credential with type of Secret text and paste base64 encoded string.
cat AuthKey_12345ABCD.p8 | base64
LS0tCk1...5cUdTTTQ #It's a result of encoding, copy it.
In Fastfile add is_key_content_base64 parameter to app_store_connect_api_key. And remove username parameter from pilot (it will cause conflict with the api_key parameter).
api_key = app_store_connect_api_key(
key_id: ENV['ASCAPI_KEY_ID'],
issuer_id: ENV['ASCAPI_ISSUER_ID'],
key_content: ENV['APP_STORE_KEY']
is_key_content_base64: true #Add this parameter ++++++++++++
)
pilot(
#username: ENV['APPLE_ID'], #Remove this row ------------
app_identifier: ENV['APP_BUNDLE_IDENTIFIER'],
.....
Did not make a deep test with other types of secrets but works great with the above solution.

Related

Retrieving secrets from HashiCorp Vault in jenkins pipeline using HashiCorp Vault Plugin

I have setup a connection between my Jenkins and Vault and by using "withVault" method
https://www.jenkins.io/doc/pipeline/steps/hashicorp-vault-plugin/#hashicorp-vault-plugin
I am retrieving vault secrets from Vault in my jenkins pipeline. Secret is stored in the environment variable github_token, which is then used to form URL for accessing git in the pipeline. Retrieving secrets works, the problem is, that $github_token variable contains asterisks.
I need it to contain actual value of the the token
def secrets = [
[path: 'ddci/data/test', engineVersion: 2, secretValues: [
[envVar: 'github_token', vaultKey: 'token']
]]
]
def configuration = [vaultUrl: 'https://vault.tools.sap/',
vaultNamespace: 's4',
vaultCredentialId: 'hashicorp_vault',
skipSslVerification: true,
engineVersion: 2]
pipeline {
agent any
stages{
stage('use token to authenticate GITHub') {
steps {
withVault([configuration: configuration, vaultSecrets: secrets]) {
sh 'git_url= https://username:${github_token}#github.tools.sap/AZURE-PIPELINES-SYSDEV/decdev-ci-verification'
git url: '$git_url', branch: 'master'
}
}
}
}
}
The $github_token variable doesn't contain asterisks, Jenkins displays any Vault secret using asterisks on console, to protect the real value.
if you want to check the $github_token value, write it to a file in the workspace, doing something like this:
echo $github_token > token.txt
Some other problem is preventing you to access the GitHub server (Is the token correct? Is the path correct? Has the Jenkins node access to the GitHub?). Log to the Jenkins node and try to execute the same command manually.

How do I return string from fastlane to jenkins groovy variable?

Have a lane in fastlane as
lane :ipa_path do |options|
“<ipa path>.ipa”
end
How to store string returned by ipa_path lane in groovy script variable?
In your Fastlane/fastfile
# Your lane in your fastfile.
lane :ipa_path do |options|
ENV["SOME_VAR"] = options[:my_passed_in_option]
# After calling build_app action to compile/create IPA
# this lane context value will exist: IPA_OUTPUT_PATH
ENV["MY_IPA_PATH"] = lane_context[SharedValues::IPA_OUTPUT_PATH]
end
In your Jenkinsfile ...
// Use this in Jenkinsfile.
stage('Test IPA Path') {
steps {
sh "bundle exec ipa_path my_passed_in_option:"some_string_value" --env jenkins"
sh "echo 'IPA Path is: ${MY_IPA_PATH}" // path_to_IPA_file.IPA
IPA_PATH = MY_IPA_PATH
sh "echo 'Some Var is: ${SOME_VAR}" // some_string_value
SOME_VARIABLE = SOME_VAR
}
}
Unfortunately, I don't think there's a way to pass values from fastlane to the parent process. The only way I've found possible so far is to write the string or such to a file.
File.write("output.txt", "your ipa path here")
From there, you can call and set it as environment variable in your server:
export MY_ENV=$(cat output.txt)
I think you can set the env variable via Jenkins UI. but the concept should be the same. Hope this helps someone.
references: 1, 2

Jenkins - Hide sensitive data from pipeline steps page (flowGraphTable)

I am writing a sensitive data to a .yml file as a string in my Jenkins groovy file. I have attached the .groovy file which would show what I am trying to achieve but it reveals the data in Pipeline steps which is also attached. Nothing shows in the console log. Value from AWS Parameter store is retrieved and passed as a string to a .yml file and this string value is shown in the pipeline steps. I am looking for a way to hide this from being shown in the Pipeline steps. I have tried using set +x but it is not hiding the string value in the pipeline steps. Any thoughts on how this can be achieved would be of great help.Screenshot
#!/usr/bin/env groovy
properties([
parameters([
string(name:'NODE_NAME', defaultValue: 'node', description: 'Node Name')
])
])
nodeName = params.NODE_NAME
node("${nodeName}") {
def AWS_REGION = "eu-west-2"
def paramPath = "path"
def paramName = "PASSWORD"
stage("Data from SSM") {
param = sh (script: "aws ssm get-parameter --name ${paramPath} --with-decryption --region ${AWS_REGION} | /var/jenkins_home/tools/jq .Parameter.Value | tr -d '\"'", returnStdout: true).trim()
sh('#!/bin/sh -e\n' + "echo '${paramName}: ${param}' >> vars.yml")
}
}
You can make use of credentials in jenkins. Go to Jenkins -> credentials -> global -> add credentials
Select either 'Username with password'/'secret text' depending on your need
This will generate a secret in jenkins
Then in your groovy file you can use the credentials as env variables which will not be printed by jenkins
withCredentials([usernamePassword(credentialsId: 'Your-Credential-ID', passwordVariable: 'pwdToken', usernameVariable: 'userToken')]){
//Use pwdToken as a variable here which will not be printed
}

Getting and put all secret in an env file on Jenkins and hashicorp vault

Currently we are building a jenkins deployment pipeline. On those build, for secret management we are using HachiCorp vault. For getting secret we using hashicorp-vault-plugin. Problem is we wants to declare all variables on pipeline scripts, like this - testing','testing_again', secret/another_test (we don't want that)
node {
// define the secrets and the env variables
// engine version can be defined on secret, job, folder or global.
// the default is engine version 2 unless otherwise specified globally.
def secrets = [
[path: 'secret/testing', engineVersion: 1, secretValues: [
[envVar: 'testing', vaultKey: 'value_one'],
[envVar: 'testing_again', vaultKey: 'value_two']]],
[path: 'secret/another_test', engineVersion: 2, secretValues: [
[vaultKey: 'another_test']]]
]
// optional configuration, if you do not provide this the next higher configuration
// (e.g. folder or global) will be used
def configuration = [vaultUrl: 'http://my-very-other-vault-url.com',
vaultCredentialId: 'my-vault-cred-id',
engineVersion: 1]
// inside this block your credentials will be available as env variables
withVault([configuration: configuration, vaultSecrets: secrets]) {
sh 'echo $testing'
sh 'echo $testing_again'
sh 'echo $another_test'
}
}
But need some things like this -
Get all the secret as key and value
Put on a env file before Building the project
After build project, destroy the env file.
Is it possible by jenkins hashicorp-vault-plugin Or get those secret from vault by curl and process by shell commend (Example is great).
in vault plugin impossible to put secrets to file. only immediately put to environment variable. After storing in env you can do whatever you want :) a that you could do something like
sh 'echo $YOURVAR > .env'
Get all the secret as key and value
by vault concept you should know secret name for access to it. not sure how it should be in your case
p.s if you need file credentials you could use
credentials
credentials-binding
plugins for jenkins

Hiding passwords in Jenkins Pipeline log output without using WithCredentials

I have a parametrized Jenkins pipeline based on a Jenkinsfile. Some of the parameters contain sensitive passwords that I don't want to appear in the job's build logs.
So my question is: can I somehow register a String within the Jenkinsfile that is then replaced - by let's say ********** - whenever it appears in the log output?
I am aware of the withCredentials step, but I can't use it, since the credentials are not stored in the Jenkins credentials store (but provided as parameters at runtime).
I found this answer here https://stackoverflow.com/a/42372859/1549950 and tried it like this:
def secrets = [
[password: firstPassword, var: 'SECRET'],
[password: secondPassword, var: 'SECRET'],
[password: thirdPassword, var: 'SECRET']
]
node() {
wrap([$class: 'MaskPasswordsBuildWrapper', varPasswordPairs: secrets]) {
// my stages containing steps...
}
}
Where firstPassword, secondPassword, thirdPassword are variables containing my passwords. But still I get the content of firstPassword... displayed plain text in the log output.
I have the Mask Password plugin installed on my Jenkins in version 2.12.0.
Basically I am searching for something like this: https://issues.jenkins-ci.org/browse/JENKINS-27486 - ticket is resolved, but no sample snippet of final implementation is given.
Actually I don't know why this didn't work in the first place, but here is the solution to the problem.
Define an array with secrets that you want to hide like this:
def splunkPassword = 'verySecretPa55w0rd'
def basicAuthPassword = 'my8asicAuthPa55w0rd'
def getSecrets() {
[
[password: splunkPassword, var: 'SECRET'],
[password: basicAuthPassword, var: 'SECRET']
]
}
Disclaimer: I don't know whether the SECRET value has an important role, copy and pasted it from some snippet and it works as expected :)
Afterwards, you can wrap any calls in your scripted pipeline like this:
node {
wrap([$class: 'MaskPasswordsBuildWrapper', varPasswordPairs: getSecrets()]) {
stage 'First Stage' { ... }
stage 'Second Stage' { ... }
}
}
All passwords provided in the getSecrets() array will then be masked like this in your build output:
SPLUNK_PASSWORD: ********
BASIC_AUTH_ADMIN_PASSWORD: ********
I think you are looking for JENKINS-36007?
Update 26 May 2020
The workaround below stopped working for me recently. My guess is that something changed in a recent Jenkins update. I was trying to avoid installing another plugin, but I eventually gave up and installed the Mask Passwords plugin.
I used the following syntax for use with parameters:
parameters {
string(name: 'USERNAME', defaultValue: '', description: 'Username')
password(name: 'PASSWORD', defaultValue: '', description: 'Password')
}
Then in the build stage:
steps {
script {
wrap([$class: 'MaskPasswordsBuildWrapper',
varPasswordPairs: [
[password: "${USERNAME}", var: 'USR'],
[password: "${PASSWORD}", var: 'PSW']
]
]) {
sh '''
echo "Username: ${USERNAME}"
echo "Password: ${PASSWORD}"
'''
}
}
}
The original workaround is below, in case anyone else tries to go down the same path.
I've discovered a workaround that is a bit of a hack, but seems to work well. The trick is to use withCredentials, but override the variable with a parameter.
Here's an example which uses the environment directive's credentials() helper method to populate an environment variable, then overrides the two additional environment variables that are automatically defined (and masked in the logs).
First, create a dummy Username with password Credentials. The Username and Password values don't matter, we just need a Credential to use as a placeholder. Enter an ID such as dummy-credentials.
Then define an environment variable using the dummy credentials, and override the automatically defined variables with the parameters (MYUSERNAME and MYPASSWORD in this example):
environment {
MY_CREDS = credentials('dummy-credentials')
MY_CREDS_USR = "${params.MYUSERNAME}"
MY_CREDS_PSW = "${params.MYPASSWORD}"
}
Use the MY_CREDS_USR and MY_CREDS_PSW environment variables wherever you need to reference the secrets. Their contents will be masked in the console log.
sh '''
echo "Username: ${MY_CREDS_USR}"
echo "Password: ${MY_CREDS_PSW}"
'''
You might have a look at https://github.com/jenkinsci/log-file-filter-plugin
This plugin allows filtering Jenkins' console output by means of regular expressions. If some pattern matches the matched string is replaced by a string that can be specified for each pattern in the configuration.
Currently the plugin doesn't support adding filter-patterns from a jenkinsfile but only from the Jenkins global settings.
Highly brutish workaround.
Write a simple script, e.g. bash, and echo the parameter credentials into some file of arbitrary format, down to your echoing approach.
E.g. basic shell script:
$ cat executor/obfuscate.sh
#!/bin/bash
echo "PASSWORD: ${AWX_PW}" > ./executor/credential.yml
In your pipeline then:
stages {
stage('Placing') {
steps {
**sh './executor/obfuscate.sh'** }
[...]
< something reading credential.yml>
}
}
Outcome, nothing showing up in console:

Resources