jenkinsci / azure-keyvault-plugin

Jenkins plugin for Azure Keyvault
https://plugins.jenkins.io/azure-keyvault/
MIT License
14 stars 21 forks source link

"Illegal base64 character" error fetching certificate #231

Closed hurcane closed 10 months ago

hurcane commented 10 months ago

Jenkins and plugins versions report

Environment ```text Jenkins: 2.435 OS: Windows Server 2012 R2 - 6.3 Java: 11.0.2 - Oracle Corporation (OpenJDK 64-Bit Server VM) --- Office-365-Connector:4.20.2 active-directory:2.34 antisamy-markup-formatter:162.v0e6ec0fcfcf6 apache-httpcomponents-client-4-api:4.5.14-208.v438351942757 authentication-tokens:1.53.v1c90fd9191a_b_ authorize-project:1.7.1 azure-credentials:293.vb_d506148f506 azure-keyvault:233.v474b_4ca_6ea_64 azure-sdk:157.v855da_0b_eb_dc2 blueocean:1.27.9 blueocean-autofavorite:1.2.5 blueocean-bitbucket-pipeline:1.27.9 blueocean-commons:1.27.9 blueocean-config:1.27.9 blueocean-core-js:1.27.9 blueocean-dashboard:1.27.9 blueocean-display-url:2.4.2 blueocean-events:1.27.9 blueocean-git-pipeline:1.27.9 blueocean-github-pipeline:1.27.9 blueocean-i18n:1.27.9 blueocean-jwt:1.27.9 blueocean-personalization:1.27.9 blueocean-pipeline-api-impl:1.27.9 blueocean-pipeline-editor:1.27.9 blueocean-pipeline-scm-api:1.27.9 blueocean-rest:1.27.9 blueocean-rest-impl:1.27.9 blueocean-web:1.27.9 bootstrap5-api:5.3.2-3 bouncycastle-api:2.30.1.77-225.v26ea_c9455fd9 branch-api:2.1135.v8de8e7899051 caffeine-api:3.1.8-133.v17b_1ff2e0599 checks-api:2.0.2 cloudbees-bitbucket-branch-source:856.v04c46c86f911 cloudbees-folder:6.858.v898218f3609d command-launcher:107.v773860566e2e commons-httpclient3-api:3.1-3 commons-lang3-api:3.13.0-62.v7d18e55f51e2 commons-text-api:1.11.0-95.v22a_d30ee5d36 conditional-buildstep:1.4.3 copyartifact:722.v0662a_9b_e22a_c credentials:1311.vcf0a_900b_37c2 credentials-binding:642.v737c34dea_6c2 data-tables-api:1.13.8-2 delivery-pipeline-plugin:1.4.2 display-url-api:2.200.vb_9327d658781 docker-commons:439.va_3cb_0a_6a_fb_29 docker-workflow:572.v950f58993843 dtkit-api:3.0.2 durable-task:523.va_a_22cf15d5e0 echarts-api:5.4.3-2 email-ext:2.102 envinject:2.908.v66a_774b_31d93 envinject-api:1.199.v3ce31253ed13 external-monitor-job:215.v2e88e894db_f8 favorite:2.200.v215a_b_a_033a_fe font-awesome-api:6.5.1-1 git:5.2.1 git-client:4.6.0 git-server:99.va_0826a_b_cdfa_d gitea:1.4.5 github:1.37.3.1 github-api:1.318-461.v7a_c09c9fa_d63 github-branch-source:1752.vc201a_0235d80 handy-uri-templates-2-api:2.1.8-22.v77d5b_75e6953 htmlpublisher:1.32 instance-identity:185.v303dc7c645f9 ionicons-api:56.v1b_1c8c49374e jackson2-api:2.15.3-372.v309620682326 jakarta-activation-api:2.0.1-3 jakarta-mail-api:2.0.1-3 javadoc:243.vb_b_503b_b_45537 javax-activation-api:1.2.0-6 javax-mail-api:1.6.2-9 jaxb:2.3.9-1 jdk-tool:73.vddf737284550 jenkins-design-language:1.27.9 jersey2-api:2.41-133.va_03323b_a_1396 jjwt-api:0.11.5-77.v646c772fddb_0 jnr-posix-api:3.1.18-1 jobConfigHistory:1229.v3039470161a_d join:1.21 jquery:1.12.4-1 jquery3-api:3.7.1-1 jsch:0.2.8-65.v052c39de79b_2 junit:1240.vf9529b_881428 ldap:711.vb_d1a_491714dc lockable-resources:1218.va_3dd45e2b_fa_7 mailer:463.vedf8358e006b_ mapdb-api:1.0.9-28.vf251ce40855d matrix-auth:3.2.1 matrix-project:818.v7eb_e657db_924 mina-sshd-api-common:2.11.0-86.v836f585d47fa_ mina-sshd-api-core:2.11.0-86.v836f585d47fa_ monitoring:1.95.0 mstest:1.0.5 nodelabelparameter:1.12.0 notification:1.17 okhttp-api:4.11.0-157.v6852a_a_fa_ec11 pam-auth:1.10 parameterized-trigger:787.v665fcf2a_830b_ pipeline-build-step:539.v8c889169451f pipeline-graph-analysis:202.va_d268e64deb_3 pipeline-groovy-lib:689.veec561a_dee13 pipeline-input-step:477.v339683a_8d55e pipeline-milestone-step:111.v449306f708b_7 pipeline-model-api:2.2151.ve32c9d209a_3f pipeline-model-definition:2.2151.ve32c9d209a_3f pipeline-model-extensions:2.2151.ve32c9d209a_3f pipeline-rest-api:2.34 pipeline-stage-step:305.ve96d0205c1c6 pipeline-stage-tags-metadata:2.2151.ve32c9d209a_3f pipeline-stage-view:2.34 plain-credentials:143.v1b_df8b_d3b_e48 plugin-util-api:3.6.0 powershell:2.1 promoted-builds:940.va_9b_59a_717a_b_1 pubsub-light:1.18 resource-disposer:0.23 run-condition:1.7 scm-api:683.vb_16722fb_b_80b_ script-security:1294.v99333c047434 snakeyaml-api:2.2-111.vc6598e30cc65 sse-gateway:1.26 ssh-credentials:308.ve4497b_ccd8f4 sshd:3.312.v1c601b_c83b_0e structs:325.vcb_307d2a_2782 throttle-concurrents:2.14 timestamper:1.26 token-macro:384.vf35b_f26814ec trilead-api:2.84.v72119de229b_7 variant:60.v7290fc0eb_b_cd versioncolumn:221.vdb_638ece0951 workflow-aggregator:596.v8c21c963d92d workflow-api:1283.v99c10937efcb_ workflow-basic-steps:1042.ve7b_140c4a_e0c workflow-cps:3826.v3b_5707fe44da_ workflow-durable-task-step:1289.v4d3e7b_01546b_ workflow-job:1385.vb_58b_86ea_fff1 workflow-multibranch:756.v891d88f2cd46 workflow-scm-step:415.v434365564324 workflow-step-api:639.v6eca_cd8c04a_a_ workflow-support:865.v43e78cc44e0d ws-cleanup:0.45 xunit:3.1.3 ```

What Operating System are you using (both controller, and any agents involved in the problem)?

Windows Server 2012 R2 - 6.3

Reproduction steps

Configure declarative pipeline with script block that uses AzureKeyVault:

script {
    if (env.TAG_NAME) {
        azureKeyVault([[envVariable: 'CODESIGNCERT', name: 'NameOfSecret', secretType: 'Certificate']]) {
            powershell label: 'Signed build', script: '.\\signedBuild.ps1'
        }
    } else
    {
        powershell label: 'Unsigned build', script: '.\\build.ps1'
    }
}

Expected Results

Expected that the steps inside the AzureKeyVault block would execute.

Actual Results

Stage fails with the following partial stack trace:

java.lang.IllegalArgumentException: Illegal base64 character 2d
at java.base/java.util.Base64$Decoder.decode0(Base64.java:743)
at java.base/java.util.Base64$Decoder.decode(Base64.java:535)
at java.base/java.util.Base64$Decoder.decode(Base64.java:558)
at org.jenkinsci.plugins.azurekeyvaultplugin.AzureKeyVaultUtil.convertAndWritePfxToDisk(AzureKeyVaultUtil.java:54)
at org.jenkinsci.plugins.azurekeyvaultplugin.AzureKeyVaultStep$ExecutionImpl.getSecretsMap(AzureKeyVaultStep.java:215)
at org.jenkinsci.plugins.azurekeyvaultplugin.AzureKeyVaultStep$ExecutionImpl.start(AzureKeyVaultStep.java:171)
at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:323)

Anything else?

We are transitioning to an HSM-backed certificate in Azure Key Vault, and we were hoping to use the plugin to avoid installing more tools in the build environment.

Are you interested in contributing a fix?

No response

timja commented 10 months ago

Can you provide the steps you used to generate / store the certificate in key vault (checking that they work to trigger the error as well).

I just generated a self-signed certificate in Key Vault and it worked fine for me.

hurcane commented 10 months ago

The certificate is a three-year code-signing certificate from Digicert which is being saved in a vault backed by an HSM, but not using a managed HSM.

The general process to create the certificate:

  1. In Azure, generate a certificate with the following attributes:
    • type "Certificate issued by a non-integrated CA"
    • Subject with company name (Digicert replaces this when issuing the cert)
    • Validity period 36 months
    • Content type: PEM
    • Advanced policy configuration: Key Size = 4096
      1. In Azure, select the cert, select Certificate Operation, and select Download CSR.
      2. On Digicert web site, place order for certificate and paste in the CSR.
      3. Wait for Digicert process to complete.
      4. In Azure, select the cert, select Certificate Operation, and select Merge request.

Maybe the content type or key size is an issue? I created a self-signed cert to test and was able to recreate the issue.

timja commented 10 months ago

Maybe the content type or key size is an issue? I created a self-signed cert to test and was able to recreate the issue.

Reproduced, it's the PEM content type.

Currently only the PFX content type is supported by the plugin.

doesn't work:

❯ az keyvault certificate show --vault-name *** --name pem-cert --query 'policy.secretProperties.contentType'
"application/x-pem-file"

works:

❯ az keyvault certificate show --vault-name **** --name my-cert --query 'policy.secretProperties.contentType'
"application/x-pkcs12"
hurcane commented 10 months ago

FYI: It turns out in my project that I didn't need to fetch the cert within the pipeline. The cert in question was a code-signing cert to be used by AzureSignTool. It only needed Azure credentials, and it worked successfully with the PEM format.

timja commented 10 months ago

good to hear, it was trivial to add support anyway so I did it in https://github.com/jenkinsci/azure-keyvault-plugin/pull/232