Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-59331

withCredentials certificate(aliasVariable: ) stores description of credential, not keystore alias name

      plugin version 1.18

      I am trying to use this certificate binding but in a simple job :
      keystore variable: CERTSTORE
      Alias Variable: MYKEY

      step as a standard shell script:

      keytool -list -v -keystore $CERTSTORE
      
      echo $MYKEY
      
      keytool -export -alias "$MYKEY" -keystore "$CERTSTORE" -rfc -file fit-kernel.cert
      

      output us

      + keytool -list -v -keystore ****
      Enter keystore password:  
      *****************  WARNING WARNING WARNING  *****************
      * The integrity of the information stored in your keystore  *
      * has NOT been verified!  In order to verify its integrity, *
      * you must provide your keystore password.                  *
      *****************  WARNING WARNING WARNING  *****************
      
      Keystore type: JKS
      Keystore provider: SUN
      
      Your keystore contains 1 entry
      
      Alias name: 1
      Creation date: Sep 12, 2019
      Entry type: PrivateKeyEntry
      
      
      *******************************************
      *******************************************
      
      
      + echo
      
      + LANG=C
      + keytool -export -alias '' -keystore **** -rfc -file fit-kernel.cert
      Enter keystore password:  
      *****************  WARNING WARNING WARNING  *****************
      * The integrity of the information stored in your keystore  *
      * has NOT been verified!  In order to verify its integrity, *
      * you must provide your keystore password.                  *
      *****************  WARNING WARNING WARNING  *****************
      
      keytool error: java.lang.Exception: Alias <> does not exist
      

      "$MYKEY" should exists but is not defined as an environment variable, I can't access my certificate.

          [JENKINS-59331] withCredentials certificate(aliasVariable: ) stores description of credential, not keystore alias name

          Kalle Niemitalo added a comment - - edited

          I see a similar result with Jenkins ver. 2.190.3, Credentials Binding Plugin 1.20, and Credentials Plugin 2.3.0. I defined a step like this in a declarative pipeline Jenkinsfile:

          withCredentials([certificate(
                  credentialsId: 'APK-signing',
                  keystoreVariable: 'AndroidSigningKeyStore',
                  passwordVariable: 'AndroidSigningStorePass',
                  aliasVariable: 'AndroidSigningKeyAlias')]) {
              writeFile encoding: 'UTF-8', file: 'AndroidSigningKeyAlias.txt', text: env.AndroidSigningKeyAlias
              // actual signing not shown
          }
          

          and, what was written to AndroidSigningKeyAlias.txt was not the "keystore alias name" documented in https://jenkins.io/doc/pipeline/steps/credentials-binding/, but instead the description of the credential. The keystore alias name was actually the same as in the PKCS#12 file from which I had imported the credential to Jenkins.

          CertificateMultiBinding#bind:

          		if(aliasVariable!=null && !aliasVariable.isEmpty())
          			m.put(aliasVariable, credentials.getDescription());
          

          I guess the original reporter had not added a description to the credential, and the alias variable was thus left empty.

          Kalle Niemitalo added a comment - - edited I see a similar result with Jenkins ver. 2.190.3, Credentials Binding Plugin 1.20, and Credentials Plugin 2.3.0. I defined a step like this in a declarative pipeline Jenkinsfile: withCredentials([certificate( credentialsId: 'APK-signing' , keystoreVariable: 'AndroidSigningKeyStore' , passwordVariable: 'AndroidSigningStorePass' , aliasVariable: 'AndroidSigningKeyAlias' )]) { writeFile encoding: 'UTF-8' , file: 'AndroidSigningKeyAlias.txt' , text: env.AndroidSigningKeyAlias // actual signing not shown } and, what was written to AndroidSigningKeyAlias.txt was not the "keystore alias name" documented in https://jenkins.io/doc/pipeline/steps/credentials-binding/ , but instead the description of the credential. The keystore alias name was actually the same as in the PKCS#12 file from which I had imported the credential to Jenkins. CertificateMultiBinding#bind : if (aliasVariable!= null && !aliasVariable.isEmpty()) m.put(aliasVariable, credentials.getDescription()); I guess the original reporter had not added a description to the credential, and the alias variable was thus left empty.

          Kalle Niemitalo added a comment - - edited

          Credentials Binding Plugin has done this ever since the certificate binding feature was added in commit 7d789a8c590fd87cb9dd61c89c894a5df26a0605 and merged in PR#39. The commit message even mentions the assumption that the credential description matches the keystore alias name, but I don't think I have seen it documented anywhere else. When I edit the description of a certificate credential, the help text "An optional description to help tell similar credentials apart" certainly gives no hint of any such requirement.

          CertificateMultiBinding already calls credentials.getKeyStore(), so perhaps it could just enumerate the returned KeyStore and get the alias name from there, without needing changes in the Credentials Plugin. If the aliasVariable parameter is specified but the KeyStore actually contains more than one key, then CertificateMultiBinding could log a warning about that, perhaps unless the description of the credential matches one of these aliases.

          If each certificate credential normally contains only one certificate and private key, then the keystore alias name is not really needed for selecting the correct certificate, and I think users are likely to choose short words like "cert" as keystore alias names. If the withCredentials step is then changed to store these to the aliasVariable, there may be a risk that Jenkins starts unnecessarily masking this word in unrelated output. Perhaps the keystore alias name should be exempt from this masking, like JENKINS-44860 requests for usernames.

          Kalle Niemitalo added a comment - - edited Credentials Binding Plugin has done this ever since the certificate binding feature was added in commit 7d789a8c590fd87cb9dd61c89c894a5df26a0605 and merged in PR#39 . The commit message even mentions the assumption that the credential description matches the keystore alias name, but I don't think I have seen it documented anywhere else. When I edit the description of a certificate credential, the help text "An optional description to help tell similar credentials apart" certainly gives no hint of any such requirement. CertificateMultiBinding already calls credentials.getKeyStore() , so perhaps it could just enumerate the returned KeyStore and get the alias name from there, without needing changes in the Credentials Plugin. If the aliasVariable parameter is specified but the KeyStore actually contains more than one key, then CertificateMultiBinding could log a warning about that, perhaps unless the description of the credential matches one of these aliases. If each certificate credential normally contains only one certificate and private key, then the keystore alias name is not really needed for selecting the correct certificate, and I think users are likely to choose short words like "cert" as keystore alias names. If the withCredentials step is then changed to store these to the aliasVariable , there may be a risk that Jenkins starts unnecessarily masking this word in unrelated output. Perhaps the keystore alias name should be exempt from this masking, like JENKINS-44860 requests for usernames.

          In the Certificate Plugin, CertificateCredentialsImpl.KeyStoreSourceDescriptor#validateCertificateKeystore apparently supports multiple certificate entries and multiple key entries in the same KeyStore. StandardCertificateCredentials.NameProvider#getSubjectDN only uses one key entry, though.

          Kalle Niemitalo added a comment - In the Certificate Plugin, CertificateCredentialsImpl.KeyStoreSourceDescriptor#validateCertificateKeystore apparently supports multiple certificate entries and multiple key entries in the same KeyStore. StandardCertificateCredentials.NameProvider#getSubjectDN only uses one key entry, though.

            Unassigned Unassigned
            shaiton Kevin Raymond
            Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: