Add support for secret files in credentials
Some refactoring:
groovy code moved to separate template
used common python module
Change-Id: Ic8e03cae92beeac80425515b7b5b6fd3a4e8aef0
diff --git a/README.rst b/README.rst
index 869ea5b..6b43e7e 100644
--- a/README.rst
+++ b/README.rst
@@ -585,6 +585,10 @@
key: SOMESSHKEY
cred_with_text_secret:
secret: SOMETEXTSECRET
+ cred_with_secret_file:
+ filename: somefile.json
+ content: |
+ { "Hello": "world!" }
Users enforcing from client:
diff --git a/_states/jenkins_credential.py b/_states/jenkins_credential.py
index 67be9a0..38e9219 100644
--- a/_states/jenkins_credential.py
+++ b/_states/jenkins_credential.py
@@ -2,71 +2,6 @@
logger = logging.getLogger(__name__)
-create_credential_groovy = u"""\
-import com.cloudbees.plugins.credentials.domains.Domain;
-import com.cloudbees.plugins.credentials.CredentialsScope;
-import hudson.util.Secret
-
-def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
- com.cloudbees.plugins.credentials.common.StandardCredentials.class,
- Jenkins.instance
- )
-def key = \"\"\"${key}
-\"\"\"
-
-def result = creds.find{
- (it instanceof com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl &&
- it.username == "${username}" &&
- it.id == "${name}" &&
- it.description == "${desc}" &&
- it.password.toString() == "${password}") ||
- (it instanceof com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey &&
- it.username == "${username}" &&
- it.id == "${name}" &&
- ("${password}" == "" || it.passphrase.toString() == "${password}") &&
- it.description == "${desc}" &&
- it.privateKeySource.privateKey.equals(key.trim())) ||
- (it instanceof org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl &&
- it.id == "${name}" &&
- it.description == "${desc}" &&
- it.secret == Secret.fromString("${secret}") )
-}
-
-if(result){
- print("EXISTS")
-}else{
- domain = Domain.global()
- store = Jenkins.instance.getExtensionList(
- 'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
- )[0].getStore()
- if ( "${clazz}" == "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl" ){
- Secret token = Secret.fromString("${secret}")
- params = 'CredentialsScope.${scope}, ${name}, ${desc}'
- credentials_new = new ${clazz}(
- CredentialsScope.${scope}, "${name}", "${desc}", token
- )
- } else {
- credentials_new = new ${clazz}(
- ${params}
- )
- }
- // remove credentails with same if before created new one, if exists
- def existingCreds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
- com.cloudbees.plugins.credentials.common.StandardCredentials.class,
- Jenkins.instance).find{it -> it.id.equals("${name}")}
- if(existingCreds){
- store.removeCredentials(domain, existingCreds)
- }
- ret = store.addCredentials(domain, credentials_new)
- if (ret) {
- print("CREATED");
- } else {
- print("FAILED");
- }
-}
-""" # noqa
-
-
def __virtual__():
'''
Only load if jenkins_common module exist.
@@ -79,58 +14,53 @@
return True
-def present(name, scope, username, password="", desc="", key=None, secret=None):
+def present(name, scope, username, password="", desc="", key=None, secret=None, filename=None, content=None):
"""
Main jenkins credentials state method
:param name: credential name
:param scope: credential scope
- :param username: username
+ :param username: username (optional)
:param password: password (optional)
:param desc: credential description (optional)
:param key: credential key (optional)
+ :param filename: file name for file credential (optional)
+ :param content: file content for file credential (optional)
:returns: salt-specified state dict
"""
- test = __opts__['test'] # noqa
- ret = {
- 'name': name,
- 'changes': {},
- 'result': False,
- 'comment': '',
- }
- result = False
- if test:
- status = 'CREATED'
- ret['changes'][name] = status
- ret['comment'] = 'Credentials %s %s' % (name, status.lower())
+ template = __salt__['jenkins_common.load_template'](
+ 'salt://jenkins/files/groovy/credential.template',
+ __env__)
+ clazz = ""
+ if key:
+ clazz = "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
+ params = 'CredentialsScope.{}, "{}", "{}", new com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey.DirectEntryPrivateKeySource(key.trim()), "{}", "{}"'.format(
+ scope, name, username, password if password else "", desc if desc else "")
+ elif secret:
+ clazz = "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl"
+ params = 'CredentialsScope.{}, "{}", "{}"'.format(
+ scope, name, desc if desc else "")
+ elif filename:
+ clazz = "org.jenkinsci.plugins.plaincredentials.impl.FileCredentialsImpl"
+ params = 'CredentialsScope.{}, "{}", "{}", "{}", SecretBytes.fromBytes("""{}""".getBytes())'.format(
+ scope, name, desc if desc else "", filename, content.encode('unicode_escape'))
else:
- clazz = ""
- if key:
- clazz = "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
- params = 'CredentialsScope.{}, "{}", "{}", new com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey.DirectEntryPrivateKeySource(key.trim()), "{}", "{}"'.format(
- scope, name, username, password if password else "", desc if desc else "")
- elif secret:
- clazz = "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl"
- params = 'CredentialsScope.{}, "{}", "{}"'.format(
- scope, name, desc if desc else "")
- else:
- clazz = "com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl"
- params = 'CredentialsScope.{}, "{}", "{}", "{}", "{}"'.format(
- scope, name, desc if desc else "", username, password)
- call_result = __salt__['jenkins_common.call_groovy_script'](
- create_credential_groovy, {"scope": scope, "name": name, "username": username if username else "", "password": password if password else "", "clazz": clazz, "params": params, "key": key if key else "", "desc": desc if desc else "", "secret": secret if secret else ""})
- if call_result["code"] == 200 and call_result["msg"] in [
- "CREATED", "EXISTS"]:
- status = call_result["msg"]
- if call_result["msg"] == "CREATED":
- ret['changes'][name] = status
- ret['comment'] = 'Credentials %s %s' % (name, status.lower())
- result = True
- else:
- status = 'FAILED'
- logger.error(
- "Jenkins credentials API call failure: %s", call_result["msg"])
- ret['comment'] = 'Jenkins credentials API call failure: %s' % (call_result[
- "msg"])
- ret['result'] = None if test else result
- return ret
+ clazz = "com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl"
+ params = 'CredentialsScope.{}, "{}", "{}", "{}", "{}"'.format(
+ scope, name, desc if desc else "", username, password)
+ return __salt__['jenkins_common.api_call'](name, template,
+ ["CREATED", "EXISTS"],
+ {
+ "scope": scope,
+ "name": name,
+ "username": username if username else "",
+ "password": password if password else "",
+ "clazz": clazz,
+ "params": params,
+ "key": key if key else "",
+ "desc": desc if desc else "",
+ "secret": secret if secret else "",
+ "fileName": filename if filename else "",
+ "content": content.encode('unicode_escape') if content else ""
+ },
+ "Credentials")
diff --git a/jenkins/client/credential.sls b/jenkins/client/credential.sls
index 1f2247f..c0962fa 100644
--- a/jenkins/client/credential.sls
+++ b/jenkins/client/credential.sls
@@ -8,6 +8,10 @@
- desc: {{ cred.get('desc', '') }}
- scope: {{ cred.get('scope','GLOBAL') }}
- secret: {{ cred.get('secret', '') }}
+ - filename: {{ cred.get('filename', '') }}
+ {%- if cred.content is defined %}
+ - content: {{ cred.get('content', '')|yaml_encode }}
+ {%- endif %}
{%- if cred.key is defined %}
- key: |
{{ cred.get('key','')|indent(6) }}
diff --git a/jenkins/files/groovy/credential.template b/jenkins/files/groovy/credential.template
new file mode 100644
index 0000000..9ce06ca
--- /dev/null
+++ b/jenkins/files/groovy/credential.template
@@ -0,0 +1,68 @@
+#!groovy
+import com.cloudbees.plugins.credentials.domains.Domain;
+import com.cloudbees.plugins.credentials.CredentialsScope;
+import com.cloudbees.plugins.credentials.SecretBytes;
+import hudson.util.Secret
+
+def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
+ com.cloudbees.plugins.credentials.common.StandardCredentials.class,
+ Jenkins.instance
+ )
+def key = """${key}
+"""
+
+def result = creds.find{
+ (it instanceof com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl &&
+ it.username == "${username}" &&
+ it.id == "${name}" &&
+ it.description == "${desc}" &&
+ it.password.toString() == "${password}") ||
+ (it instanceof com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey &&
+ it.username == "${username}" &&
+ it.id == "${name}" &&
+ ("${password}" == "" || it.passphrase.toString() == "${password}") &&
+ it.description == "${desc}" &&
+ it.privateKeySource.privateKey.equals(key.trim())) ||
+ (it instanceof org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl &&
+ it.id == "${name}" &&
+ it.description == "${desc}" &&
+ it.secret == Secret.fromString("${secret}") ) ||
+ (it instanceof org.jenkinsci.plugins.plaincredentials.impl.FileCredentialsImpl &&
+ it.id == "${name}" &&
+ it.description == "${desc}" &&
+ it.fileName == "${fileName}" &&
+ it.content.text == """${content}""" )
+}
+
+if(result){
+ print("EXISTS")
+}else{
+ domain = Domain.global()
+ store = Jenkins.instance.getExtensionList(
+ 'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
+ )[0].getStore()
+ if ( "${clazz}" == "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl" ){
+ Secret token = Secret.fromString("${secret}")
+ params = 'CredentialsScope.${scope}, ${name}, ${desc}'
+ credentials_new = new ${clazz}(
+ CredentialsScope.${scope}, "${name}", "${desc}", token
+ )
+ } else {
+ credentials_new = new ${clazz}(
+ ${params}
+ )
+ }
+ // remove credentails with same if before created new one, if exists
+ def existingCreds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
+ com.cloudbees.plugins.credentials.common.StandardCredentials.class,
+ Jenkins.instance).find{it -> it.id.equals("${name}")}
+ if(existingCreds){
+ store.removeCredentials(domain, existingCreds)
+ }
+ ret = store.addCredentials(domain, credentials_new)
+ if (ret) {
+ print("CREATED");
+ } else {
+ print("FAILED");
+ }
+}