Jenkins pipelines credential variable not getting passed - jenkins

Can't seem to figure this one out, the variables seems to be null when I run the following step (in my pipeline):
steps {
withCredentials([certificate(credentialsId: 'pfxCert', keystoreVariable: 'pfxPath', passwordVariable: 'pfxPassword')]) {
powershell '''
$keyContainerName = "somekey123"
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($pfxPath, $pfxPassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$exportPrivateKeyInformation = $true
$certXml = $cert.PrivateKey.ToXmlString($exportPrivateKeyInformation)
$csp = New-Object System.Security.Cryptography.CspParameters
$csp.KeyContainerName = $keyContainerName
$csp.Flags = [System.Security.Cryptography.CspProviderFlags]::UseMachineKeyStore -bor [System.Security.Cryptography.CspProviderFlags]::NoPrompt # -bor is biwise or
$csp.KeyNumber = [System.Security.Cryptography.KeyNumber]::Signature
$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider $csp
$rsa.FromXmlString($certXml)
$rsa.Clear()
'''
}
Here's the error output:
powershell.exe : Exception calling "Import" with "3" argument(s): "Array may not be empty or null.
I have another step with secret text credentials working, but it uses bat instead of powershell. Anyone know what I'm doing wrong? Thanks in advance.

Related

Terraform 14.2: 'Error: Invalid index: This value does not have any indices' on destroy-time provisioner on a destroy-time resource

I have a create provisioner and a destroy provisioner. I've read that apparently, triggers might solve this problem, so they're integrated here, but while this succeeds to build the resources, it doesn't let them destroy this module.thingx.null_resource.script-stuff resource.
I'm not sure I'm using triggers correctly here, and it's more confusing that create time apply works fine, but the destroy time apply fails with the mentioned error.
Here is the module null resource that apparently the error is referring to; includes both the create and destroy time provisioners:
resource "null_resource" "script-stuff" {
### -- testing triggers
triggers = {
dns_zones = var.dns_zones[each.key]
dnat_ip = google_compute_instance.server[each.key].network_interface.0.access_config.0.nat_ip
pem = tls_private_key.node_ssh[each.key].private_key_pem
} ### -- end testing
depends_on = [google_compute_instance.server, google_project_iam_member.list-sa]
for_each = var.list_map
provisioner "remote-exec" {
when = create
inline = [
"cat ${var.dns_zones[each.key]} > /dev/null",
"sensitive-script.sh --create"
]
connection {
type = "ssh"
host = google_compute_instance.server[each.key].network_interface[0].access_config[0].nat_ip
user = "common-user"
private_key = tls_private_key.node_ssh[each.key].private_key_pem
}
}
provisioner "remote-exec" {
when = destroy
inline = [
# "echo ${var.dns_zones[each.key]} > /dev/null", #<-- this doesn't work when terraform is destroying
"echo ${self.triggers.dns_zones[each.key]} > /dev/null",
"sensitive-script.sh --destroy"
]
connection {
type = "ssh"
#host = google_compute_instance.server[each.key].network_interface[0].access_config[0].nat_ip #<-- this doesn't work when terraform is destroying
host = self.triggers.dnat_ip
user = "common-user"
#private_key = tls_private_key.node_ssh[each.key].private_key_pem #<-- this doesn't work when terraform is destroying
private_key = self.triggers.pem
}
}
}
destroy triggered provisioners do not support variables as explained in this GitHub issue:
Allow destroy-time provisioners to access variables
So you can't have any variable in "echo ${var.dns_zones[each.key]} > /dev/null".

How to use `StaplerResponse rsp` in `AsyncResourceDisposer.doStopTracking()`

I'm trying to remove (stop tracking) trackig item from Jenkins AsyncResourceDisposer (${JENKINS_URL}/administrativeMonitor/AsyncResourceDisposer) via groovy scripts (${JENKINS_URL}/script).
According to the Javadoc and source code
// Javadoc
#Restricted(value=org.kohsuke.accmod.restrictions.DoNotUse.class)
public org.kohsuke.stapler.HttpResponse doStopTracking(#QueryParameter
int id,
org.kohsuke.stapler.StaplerResponse rsp
)
// source code
#Restricted(DoNotUse.class)
#RequirePOST
public HttpResponse doStopTracking(#QueryParameter int id, StaplerResponse rsp) {
...
}
I'd like to know how to add org.kohsuke.stapler.StaplerResponse rsp in doStopTracking(int id, org.kohsuke.stapler.StaplerResponse rsp):
import org.jenkinsci.plugins.resourcedisposer.AsyncResourceDisposer
AsyncResourceDisposer disposer = AsyncResourceDisposer.get()
disposer.backlog.each {
disposer.doStopTracking( it.id, <what should I put here> )
}
Current I can get the item id, and the other informaitons like below:
import org.jenkinsci.plugins.resourcedisposer.AsyncResourceDisposer
AsyncResourceDisposer disposer = AsyncResourceDisposer.get()
String url = Jenkins.instance.rootUrl + disposer.url
disposer.getBacklog().each { item ->
println "\n${item.id} : \t${url}/stopTracking/?id=${item.id} : \t${item.class.simpleName} : \n" +
"\t${item.getLastState().getDisplayName()} : \n" +
"\t${item.getDisposable().node} : ${item.getDisposable().path}\n" +
"\t${item.toString()}"
}
If I'm go to the url "${url}/stopTracking/?id=${item.id}" in browser (login first), the item can be removed after click RETRY USING POST (as below)
So... I'm using the API call curl -H <crumbIssues> -X POST <url> by passed the disposer.doStopTracking(int, org.kohsuke.stapler.StaplerResponse) (still really wants know how to use it)
Before running the following script, Strict Crumb Issuers Plugin is necessary to be installed and configured (or setup -Dhudson.security.csrf.DefaultCrumbIssuer.EXCLUDE_SESSION_ID=true) due to SECURITY-626 : Improved CSRF protection since:
obtain a crumb using the /crumbIssuer/api URL will now fail to perform actions protected from CSRF unless the scripts retain the web session ID in subsequent requests.
Here is details:
import org.jenkinsci.plugins.resourcedisposer.AsyncResourceDisposer
import org.jenkinsci.plugins.strictcrumbissuer.StrictCrumbIssuer
AsyncResourceDisposer disposer = AsyncResourceDisposer.get()
StrictCrumbIssuer issuer = jenkins.model.Jenkins.instance.crumbIssuer
String jenkinsCrumb = "${issuer.crumbRequestField}:${issuer.crumb}"
String url = Jenkins.instance.rootUrl + disposer.url
disposer.getBacklog().each { item ->
println "\n ~~> removeing ${item.id} : "
[ 'bash', '-c', 'curl -s ' +
'-u <user>:<token> ' +
'-X POST ' +
"-H \"Content-Type: application/json\" " +
"-H \"Accept: application/json\" " +
"-H \"${jenkinsCrumb}\" " +
"${url}/stopTracking/?id=${item.id} "
].execute().with{
def stdout = new StringBuffer()
def stderr = new StringBuffer()
it.waitForProcessOutput( stdout, stderr )
println "EXIT CODE: ${it.exitValue()}"
println "ERROR: ${stderr}"
println "OUTPUT: ${stdout}"
}
}
Although, I still have a question... As we know that if the groovy script running in ${JENKINS_URL}/script, which means the "runner" is the administrator, so, how I can remove the specific user authorication '-u <user>:<token>' (by using the jenkins administrator authorication) in curl ?

GCE: Setting Environment Variables from Metadata

I am using Packer to generate an image on Google Compute Engine, and Terraform to create the instance. I have set this metadata:
key: env_vars
value: export test=10
Packer is using a script with something like this inside:
curl "http://metadata.google.internal/computeMetadata/v1/project/attributes/env_vars?recursive=tru&alt=text" -H "Metadata-Flavor: Google" -o /tmp/env_vars.sh
source /tmp/env_vars.sh # or . /tmp/env_vars.sh
The problem is that when I create an instance using this image through Terraform the env variables are not available. That means, If I run printenv or echo $test, it is empty.
Even if I write a startup-script for the instance, it doesn't work.
But, if I run the same exact script inside the instance via SSH, it does work.
In all scenarios described above, the file env_vars.sh is created.
I just want to set the env vars from my metadata for any instance.
Any suggestion on how can I achieve this?
EDIT:
Here's the terraform code:
# create instance
resource "google_compute_instance" "default" {
count = 1
name = var.machine_name
machine_type = var.machine_type
zone = var.region_zone
tags = ["allow-http-ssh-rule"]
boot_disk {
initialize_params {
image = var.source_image
}
}
network_interface {
network = "default"
access_config {
// Ephemeral IP
}
}
}
I have reproduced your issue in my own project, and you are right it seems that exportdoes not work on the strat-up script.
I also tried creating a start-up script in a bucket but it does not work.
On the other hand I was able to set the env var in my project:
I’m using a debian-9 image, so, I edited the /etc/profile to add the env vars.
I use the following code to create my VM with env variables:
provider "google" {
project = "<<PROJECT-ID>>"
region = "us-central1"
zone = "us-central1-c"
}
resource "google_compute_instance" "vm_instance" {
name = "terraform-instance"
machine_type = "f1-micro"
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
# A default network is created for all GCP projects
network = "default"
access_config {
}
}
# defining metadata
metadata = {
foo = "bar"
}
metadata_startup_script = "echo ENVVAR=DEVELOPMENT2 >> /etc/profile"
}
After the creation of my instance I was able to see the correct values:
$ echo $ENVVAR
DEVELOPMENT2

I need a way to authenticate sharepointonline api connection without user consent using ARM or any powershell

I want automation to authenticate sharepoint online api connection without user consent in Azure as I want to run the code in azuredveops pipeline and the code which I got got does open a custom form and ask for user consent.It is good if I don't have to run it through devops pipeline but in my case yes I need to run authorization through code without user/graphical intervention
I have tried below code which works fine on my local but as I explained,it needs user consent which won't work in azuredevops pipeline world
[string] $ResourceGroupName = '*****',
[string] $ResourceLocation = '******',
[string] $api = 'office365',
[string] $ConnectionName = 'SharepointOnline',
[string] $subscriptionId = '*****'
)
#OAuth window for user consent
Function Show-OAuthWindow {
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object -TypeName System.Windows.Forms.Form -Property #{Width=600;Height=800}
$web = New-Object -TypeName System.Windows.Forms.WebBrowser -Property #{Width=580;Height=780;Url=($url -f ($Scope -join "%20")) }
$DocComp = {
$Global:uri = $web.Url.AbsoluteUri
if ($Global:Uri -match "error=[^&]*|code=[^&]*") {$form.Close() }
}
$web.ScriptErrorsSuppressed = $true
$web.Add_DocumentCompleted($DocComp)
$form.Controls.Add($web)
$form.Add_Shown({$form.Activate()})
$form.ShowDialog() | Out-Null
}
#login to get an access code
#Login-AzureRmAccount
#select the subscription
$ResourceLocation = (Get-AzureRmResource -ResourceGroupName CI | Select-Object Location)[0].Location
$subscription = Select-AzureRmSubscription -SubscriptionId $subscriptionId
#Get the connection and create if wasn't already created
$connection = Get-AzureRmResource -ResourceType "Microsoft.Web/connections" -ResourceGroupName $ResourceGroupName -ResourceName $ConnectionName -ErrorAction SilentlyContinue
if(-not $connection) {
$connection = New-AzureRmResource -Properties #{"api" = #{"id" = "subscriptions/" + $subscriptionId + "/providers/Microsoft.Web/locations/" + $ResourceLocation + "/managedApis/" + $api}; "displayName" = $ConnectionName; } -ResourceName $ConnectionName -ResourceType "Microsoft.Web/connections" -ResourceGroupName $ResourceGroupName -Location $ResourceLocation -Force
}
#else get the connection
else{
$connection = Get-AzureRmResource -ResourceType "Microsoft.Web/connections" -ResourceGroupName $ResourceGroupName -ResourceName $ConnectionName
}
Write-Host "connection status: " $connection.Properties.Statuses[0]
$parameters = #{
"parameters" = ,#{
"parameterName"= "token";
"redirectUrl"= "https://online.microsoft.com/default/authredirect"
}
}
#get the links needed for consent
$consentResponse = Invoke-AzureRmResourceAction -Action "listConsentLinks" -ResourceId $connection.ResourceId -Parameters $parameters -Force
$url = $consentResponse.Value.Link
#prompt user to login and grab the code after auth
Show-OAuthWindow -URL $url
$regex = '(code=)(.*)$'
$code = ($uri | Select-string -pattern $regex).Matches[0].Groups[2].Value
Write-output "Received an accessCode: $code"
if (-Not [string]::IsNullOrEmpty($code)) {
$parameters = #{ }
$parameters.Add("code", $code)
# NOTE: errors ignored as this appears to error due to a null response
#confirm the consent code
Invoke-AzureRmResourceAction -Action "confirmConsentCode" -ResourceId $connection.ResourceId -Parameters $parameters -Force -ErrorAction Ignore
}
#retrieve the connection
$connection = Get-AzureRmResource -ResourceType "Microsoft.Web/connections" -ResourceGroupName $ResourceGroupName -ResourceName $ConnectionName
Write-Host "connection status now: " $connection.Properties.Statuses[0]
You must first create a Automation account with AzureRunAs credentials. Then create your Runbook inside your automation account.
About AzureRunAs account - docs
My first Runbook - docs
From Azure Devops i found this blog which can be of help

Grails Gradle Docker Plugin bmuschko.github.io/gradle-docker-plugin/ throws Could not set unknown property 'env'

| Error Error initializing classpath: Could not set unknown property 'env' for task ':createPostgresContainer' of type com.bmuschko.gradle.docker.tasks.container.DockerCreateContainer. (Use --stacktrace to see the full trace)
https://bmuschko.github.io/gradle-docker-plugin/
I was using this Gradle Docker Plugin to setup a Postgres docker container to test out some database related stuff on the Mac, by following the example here. http://guides.grails.org/grails-docker-external-services/guide/index.html
But it doesn't seem to work out because of an env string that cannot be set like so:
task createPostgresContainer(type: DockerCreateContainer, dependsOn: pullPostgresImage) {
group = "docker"
ext {
pgContainerName = "demo-db"
dbName = "demo-db"
dbPort = 5432
dbPassword = "kevintan"
}
description = 'Creates PostgreSQL container'
containerName = pgContainerName
imageId = pullPostgresImage.imageName+":"+pullPostgresImage.tag
portBindings = ["${dbPort}:5432"]
env = [
"POSTGRES_PASSWORD=${dbPassword}",
"POSTGRES_DB=${dbName}",
] as String[]
onError { e ->
if (e.class.simpleName in ['BadRequestException', 'ConflictException']) {
logger.warn 'Container already exists'
} else {
throw e
}
}
}
Is there any way to set the env? Or am I missing something?
Never mind. I forgot to read the changelogs.
Removed DockerCreateContainer.env, replaced by DockerCreateContainer.envVars

Resources