Unable to use aws cli from Jenkins Groovy - jenkins

I am trying to write Jenkins post-initialisation scripts in Groovy that use the AWS CLI. My Jenkins lives behind a corporate proxy, and I configured it as myproxy port 3128 with a username and password, and a no_proxy of "10.*.*.*,ap-southeast-2.compute.internal,localhost,127.0.0.1,myothernoproxydomains.com".
The Groovy code I am trying is as follows:
def sg = "curl http://169.254.169.254/latest/meta-data/security-groups".execute().text
"aws ec2 describe-security-groups \
--region ap-southeast-2 \
--filters Name=group-name,Values=${sg} \
--query SecurityGroups[0].GroupId \
--output text".execute().text
If I comment out the second command, and run it in the Jenkins Script console, it runs fine and I can print the security group name. But if I allow the second command to run, I eventually get a message from my Chrome browser,
This page isn't working", myjenkins.mydomain.com took too long to respond. HTTP ERROR 504.
The Jenkins has no trouble using the HTTP proxy in other contexts, e.g. downloading packages, plugins etc.
I note that environment variables relating to the HTTP proxy do not appear in System.genenv:
System.getenv()
Result: {PATH=/sbin:/usr/sbin:/bin:/usr/bin, SHELL=/bin/bash, LOGNAME=jenkins, PWD=/, USER=jenkins, LANG=en_US.UTF-8, SHLVL=2, HOME=/var/lib/jenkins, _=/etc/alternatives/java}
I have seen Groovy code that calls the AWS CLI work on other Jenkinses at other sites. I think it might be somehow proxy-related?
Am I doing anything wrong? Any ideas on what the issue could be?

I think the issue is that the call to 169.254.169.254 is not passing through the proxy, so the CLI isn't timing out it is the AWS call to the meta data store. Add that into your NO_PROXY value and hopefully that should resolve the issue.
The other option is to turn off the proxy, they are evil :)

If you call it with Error Handling it won't cause a 504 Gateway Timed Out
def sg = "curl http://169.254.169.254/latest/meta-data/security-groups".execute().text
def sout = new StringBuilder(), serr = new StringBuilder()
def proc = 'aws ec2 describe-security-groups --region ap-southeast-2 --filters Name=group-name,Values=${sg} --query SecurityGroups[0].GroupId --output text'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout\nerr> $serr"
This still doesn't work and returns empty. I can't get a simple aws ssm get-parameter to work so a proxy issue seems to be the culprit. I'll update if I get it working.

Related

How to connect to IBM Cloud Redis from Ruby on Rails application

Migrating from one service to IBM Cloud for Redis.
I cannot find the correct configuration to connect using TLS. Everything I find on this is related to Heroku. and it ignores verifying the TLS/SSL connection.
I cannot find how to configure our Sidekiq/Redis to connect.
I do have a certificate from the IBM Cloud dashboard and I suspect I have to pass that along somehow.
Configure the Sidekiq.yml like this
:redis:
:url: "rediss://:< PWD >#< DB Name >:< PORT >/0"
:namespace: "app"
:ssl_params:
ca_file: 'path/to/cert'
I keep getting back the error Redis::CommandError - WRONGPASS invalid username-password pair or user is disabled.: however using these same credentials in the migration script I am able to connect to the DB, so the credentials are ok, I think it is not including the certificate correctly and I cannot find the correct way to do this
The sidekiq.yml configuration looks good to me, just make sure this has correct complete path
ca_file: 'path/to/cert'
and change the redis url to
:url: "rediss://< PWD >#< DB Name >:< PORT >/0"
further info you can read from here for TLS secured connection.
I'm not familiar with sidekiq.yml. But I've configured redlin with redis using a python script you can find here: https://github.com/IBM-Cloud/vpc-transit/blob/master/py/test_transit.py. Maybe the configuration is similar.
The relevant code is:
def vpe_redis_test(fip, resource):
"""execute a command in fip to verify postgresql is accessible"""
redis = resource["key"]
credentials = redis["credentials"]
cert_data = credentials["connection.rediss.certificate.certificate_base64"]
cli_arguments = credentials["connection.cli.arguments.0.1"]
command = f"""
#!/bin/bash
set -ex
if [ -x ./redli ]; then
echo redli already installed
else
curl -LO https://github.com/IBM-Cloud/redli/releases/download/v0.5.2/redli_0.5.2_linux_amd64.tar.gz
tar zxvf redli_*_linux_amd64.tar.gz
fi
./redli \
--long \
-u {cli_arguments} \
--certb64={cert_data} << TEST > redis.out
set foo working

Automate Setting Jenkins Credentials and Global Variables

I have Terraform+Ansible script that automates the deployment of a Jenkins server. However, I'd also like to pre-load that server with "Global" environment variables (Found in "Manage Jenkins" > "Configure System" > "Global Properties" > "Environment Variables"). I'm also looking to automatically set a few Jenkins credentials (found in "Manage Jenkins" > "Manage Credentials").
From what I understand, the credentials are stored encrypted in a file called /var/lib/jenkins/credentials.xml. And the global properties might be stored in config.xml in the same Jenkins directory, though the variables don't look very structured. I might be able to parse out the config.xml and add some values. But I'm wondering how I can create an encrypted secret that can be added to the credentials.xml.
Are there any tools or strategies for automating the creation of secrets and environment variables in Jenkins? I'm hoping that there's a better way to automate this other than parsing the xml documents. Any advice is much appreciated.
You shouldn't be manually altering these files. You can use one of the following options to automate Credential and Global variable creation.
Jenkins API.
Jenkins CLI.
Python-jenkinsapi. (Python wrapper for Jenkins API)
How to use Jenkins API to create credentials
Following commands need curl and jq. Execute in the same session.
# Change the following appropriately
JENKINS_URL="http://localhost:8080"
JENKINS_USER=admin
JENKINS_USER_PASS=admin
Get the Crumb
JENKINS_CRUMB=$(curl -u "$JENKINS_USER:$JENKINS_USER_PASS" -s --cookie-jar /tmp/cookies $JENKINS_URL'/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
Get the Access token
ACCESS_TOKEN=$(curl -u "$JENKINS_USER:$JENKINS_USER_PASS" -H $JENKINS_CRUMB -s \
--cookie /tmp/cookies $JENKINS_URL'/me/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken' \
--data 'newTokenName=GlobalToken' | jq -r '.data.tokenValue')
Create Credentials
curl -u $JENKINS_USER:$ACCESS_TOKEN \
-H $JENKINS_CRUMB \
-H 'content-type:application/xml' \
"$JENKINS_URL/credentials/store/system/domain/_/createCredentials" \
-d '<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
<id>TestCredentials</id>
<description>This is sample</description>
<username>admin2</username>
<password>admin2</password>
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>'
Note: The credential create URL format is /credentials/store/CREDENTIALS_STORE_NAME/domain/DOMAIN_NAME/ Change this appropriately if you want to create the Credential in a custom location. The easiest way to get this URL is by navigating to a existing credential from the UI and copying the URL.
How to create Credentials from Jenkins CLI
# Change the following appropriately
JENKINS_URL="http://localhost:8080"
JENKINS_USER=admin
JENKINS_USER_PASS=admin
Download the Jenkins CLI Jar
wget $JENKINS_URL/jnlpJars/jenkins-cli.jar
Create a file named cred.xml with the following content.
<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
<scope>GLOBAL</scope>
<id>PassID</id>
<username>Username</username>
<password>password</password>
<description>Description</description>
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
Create credentials
java -jar jenkins-cli.jar -s $JENKINS_URL -auth $JENKINS_USER:$JENKINS_USER_PASS create-credentials-by-xml system::system::jenkins _ < cred.xml
How to create credentials with Jenkins Python API
Following is a simple sample to create Global credentials using Jenkins Python API.
from api4jenkins import Jenkins
j = Jenkins('http://localhost:8080', auth=('admin', 'admin'))
xmlPayload = '''<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
<id>user-id</id>
<username>user</username>
<password>upassword</password>
<description>user id for testing</description>
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>'''
j.credentials.create(xmlPayload)

Validating Jenkinsfiles within a Jenkinsfile

The docs state to verify a Jenkinsfile you can do as follows
Linting via HTTP POST using curl
# curl (REST API)
# Assuming "anonymous read access" has been enabled on your Jenkins instance.
# JENKINS_URL=[root URL of Jenkins controller]
# JENKINS_CRUMB is needed if your Jenkins controller has CRSF protection enabled as it should
JENKINS_CRUMB=`curl "$JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)"`
curl -X POST -H $JENKINS_CRUMB -F "jenkinsfile=<Jenkinsfile" $JENKINS_URL/pipeline-model-converter/validate
At the moment I am just trying to get the crumb. I am trying to do this programmatically in a pipeline, however issuing the curl command throws an error every time. script.sh: Syntax error: "(" unexpected
I have tried escaping the ( character but that is a different error, it works without the xpath extension but it would be cleaner to include this. I have tried to use jenkins Snippet Generator and when I plug in the command it gives response = sh returnStdout: true, script: '''curl -s $JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\\":\\",//crumb) '''. However running this also gives an error.

Running sfdx force:auth:web:login on jenkins job

I have a Jenkins job to deploy metadata to a given org. This is meant to be used as a first time setup method for new metadata. I have a jenkinsfile that can run the sfdx commands, and I'm trying to run force:auth:web:login.
agent none
steps {
script {
withEnv(["HOME=${env.WORKSPACE}", "MY_TOOL_DIR=${tool name: 'sfdx', type: 'com.cloudbees.jenkins.plugins.customtools.CustomTool'}"]){
def sfdx = "SFDX_USE_GENERIC_UNIX_KEYCHAIN=true ${MY_TOOL_DIR}/sfdx"
sh "${sfdx} force:auth:web:login --setalias deployOrg"
sh "${sfdx} force:mdapi:deploy -c -d ../MetadataFiles -u deployOrg -w 10"
}
}
This runs, but it doesn't open up the prompt to do the actual login. I was trying to do this before with ant, which was running but was refusing to deploy customSite data. So I could do either or, I just have to fix one error or the other. Is there a way to authorize a regular org (not devhub) like with JWT flows, or is that fully impossible?
Any help is much appreciated.
Is there a way to authorize a regular org (not devhub) like with JWT flows, or is that fully impossible?
Yes. The JWT Flow is in no way specific to Dev Hub orgs. You can authorize those orgs using JWT and a stored certificate following the instructions in the Salesforce DX Developer Guide.

No Valid crumb is included in that request

I have one jenkins server A where I am trying to create a scripted pipeline but I have to call another job (Job1) on another jenkins server B.
In order to do that I am using REST API with crumb in Header. I retrieve my crumb by running the following command on my browser.
http://myhudson.com/crumbIssuer/api/json?xpath=concat(//crumbRequestField,":",//crumb)"
I tried different commands mentioned below but there is no luck.Please advise some thing. I do have access or permission for triggering build on both of the servers. I am executing below commands from Jenkins server A with details of Server B.
1. curl -v -u Username:<API_TOKEN> -X POST http://UsedrName:<API_TOKEN>#myjenkins.com/job/Test_job/build?token=<API_TOKEN> -H Jenkins-Crumb:<Crumb number>
2. curl -v -X POST http://UsedrName:<API_TOKEN>#myjenkins.com/job/Test_job/build?token=<API_TOKEN> -H Jenkins-Crumb:<Crumb number>
3. curl -v -u Username:<API_TOKEN> -X POST http://UsedrName:<API_TOKEN>#myjenkins.com/job/Test_job/build?token=<API_TOKEN> -H .crumb:<Crumb number>
did jenkins API work for you, https://wiki.jenkins.io/display/JENKINS/Remote+access+API you can trigger remote jobs
You need to use Build With Parameters Plugin for it . you can write a shell script in build option to call the another jenkins job on other server.
shell script snippet :curl -X POST -u userid of other server:API token of other server {jenkins server url of B job /job/jobname}
To get rid of this error i got Jenkins-Crumb by using wget command.
Trigger parameterized build with curl and crumb
I was able to execute remote parameter job.
I faced the same issue and it was because on that port something else is running and jenkins is giving Error as "No Valid crumb is included in that request" thus changed the port in server.xml and things worked.

Resources