0

I am currently trying to do the following inside of a declarative pipeline in Jenkins. I have a certificate in a file and I am trying to put this in a kubernetes secret. Now my problem is the following.

As the file contains newlines passing it as a parameter to kubectl will end the input right there and the command will fail. So I need to escape the newlines. My approach is the following

  1. cat the file and pipe it to
  2. base64
  3. place \n instead of newlines.

Now in the shell this works perfectly fine with

cat ./certs/mycert.pem | base64 | sed ':a;N;$!ba;s/\n/\\n/g'

However trying to use it in the Jenkinsfile as

sh(script: "cat ./certs/key.pem | base64 | sed ':a;N;$!ba;s/\n/\\n/g'", returnStdout: true);

will fail with the error

illegal string body character after dollar sign;

ok this one is easy. I can escape the dollar sign but unfortunately things don't end here. I will then get the error

sed: -e expression #1, char 10: unterminated `s' command

and I can go on and try to escape everything twice which will make sed stopping to fail but the output then has no \n but just regular newlines again.

Any ideas how to use this regex properly inside of my sh method?

relief.melone
  • 3,042
  • 1
  • 28
  • 57
  • you have to escape `'$'`, and each `'\'` signs. strange that you try to encode pem file with base64 because pem-file already has base64-encoded content. ps: you could replace this with groovy code – daggett Aug 27 '19 at 09:08
  • 1
    another approach to use dollar-slashy string: http://docs.groovy-lang.org/latest/html/documentation/#_string_summary_table. `$/cat ./certs/mycert.pem | base64 | sed ':a;N;$!ba;s/\n/\\n/g'/$`. it should work in your case – daggett Aug 27 '19 at 09:20
  • Why are you converting to base64 a pem file (which is already base64 encoded)? – oliv Aug 27 '19 at 09:30
  • Its because in Kubernetes you need to pass the value as base64 encoded when creating a secret. even if it is a certificate (in which eg. -----BEGIN CERTIFICATE.. is not encoded) – relief.melone Aug 27 '19 at 10:10
  • Thanks alot for the dollar slashy. That was exactly what I needed. You want to add it as answer? I'd accept it ;) – relief.melone Aug 27 '19 at 10:39

1 Answers1

3

so, 3 main variants:

  1. escape all special symbols (in your case $ and \) using \
def b = sh(script: "cat ./certs/mycert.pem | base64 | sed ':a;N;\$!ba;s/\\n/\\\\n/g'", returnStdout: true)
  1. use dollar-slashy string quotation. in your case it will work without additional symbol escaping.
def b = sh(script: $/cat ./certs/mycert.pem | base64 | sed ':a;N;$!ba;s/\n/\\n/g'/$, returnStdout: true)
  1. write required functionality in groovy
def b = new File('./certs/mycert.pem').bytes.encodeBase64().toString()

no need to replace \n because encodeBase64() returns single-line base64 value

daggett
  • 26,404
  • 3
  • 40
  • 56
  • Variant 3 actually seems to be the cleanest unfortunately using those java methods is permitted by default in the Jenkinsfile :/ – relief.melone Aug 27 '19 at 11:03