Hello rittneje
I have implemented a workaround for FileCredentialsImpl.
Created shared lib method (vars/stringToSecretBytes.groovy)
import com.cloudbees.plugins.credentials.SecretBytes
def call(s) {
return SecretBytes.fromString(s.bytes.encodeBase64().toString())
}
in repo for job dsl:
./Jenkinsfile
./secrets.yaml
./seed.groovy
secrets.yaml
- id: secretFile
secret: |
secret text file
type: file
fileName: secret.txt
description: secretFile
- id: secretText
secret: 'secret text'
type: text
description: secretText
Jenkinsfile:
node {
stage('seed') {
checkout scm
def secrets = readYaml file: 'secrets.yaml'
def i = 0
for (s in secrets) {
if (s.type == 'file') {
secrets[i].secret = stringToSecretBytes(s.secret).toString() }
i += 1
}
writeJSON file: 'secrets.json', json: secrets
jobDsl targets: 'seed.groovy', removedJobAction: 'DELETE'
}
}
seed.groovy:
def secrets = new groovy.json.JsonSlurper().parseText(readFileFromWorkspace('secrets.json'))
folder('folderName') {
properties {
folderCredentialsProperty {
domainCredentials {
domainCredentials {
domain {
name('')
description('')
}
}
}
}
}
if (secrets.any{it.type == 'file' || it.type == 'text'}) {
configure { folder ->
def configNode = folder / 'properties' / 'com.cloudbees.hudson.plugins.folder.properties.FolderCredentialsProvider_-FolderCredentialsProperty' / 'domainCredentialsMap' / 'entry' / 'java.util.concurrent.CopyOnWriteArrayList'
for (c in secrets) {
if (c.type == 'file') {
configNode << 'org.jenkinsci.plugins.plaincredentials.impl.FileCredentialsImpl' {
id(c.id)
description(c.description)
fileName(c.fileName)
secretBytes(c.secret)
}
}
if (c.type == 'text') {
configNode << 'org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl' {
id(c.id)
description(c.description)
secret(hudson.util.Secret.fromString(c.secret).getEncryptedValue())
}
}
}
}
}
}
It works for me:

The secret with the file is correct. For example:
node {
withCredentials([file(credentialsId: 'secretFile', variable: 'TEST')]) {
sh "cat ${TEST}"
}
}
This pipeline printed:
15:30:39 [Pipeline] {
15:30:39 [Pipeline] withCredentials
15:30:39 Masking supported pattern matches of $TEST
15:30:39 [Pipeline] {
15:30:39 [Pipeline] sh
15:30:39 Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
15:30:39 Affected argument(s) used the following variable(s): [TEST]
15:30:39 See https:15:30:40 + cat ****
15:30:40 secret text file
15:30:40 [Pipeline] }
15:30:41 [Pipeline] 15:30:41 [Pipeline] }
15:30:41 [Pipeline] 15:30:41 [Pipeline] End of Pipeline
15:30:41 Finished: SUCCESS
"secret text file" from secrets (in secrets.yaml)
secrets.yaml I used for storage convenience (for example encrypt with mozilla sops), you can rework the example for your cases
I was able to work around this bug using the configure option for string creds.
Unfortunately, I still cannot get file creds to work properly. It requires using com.cloudbees.plugins.credentials.SecretBytes, but attempting to do so gives all sorts of bizarre errors, like unable to resolve class com.cloudbees.plugins.credentials.SecretBytes or No such property: cloudbees for class: java.lang.String.