fabric8io / docker-maven-plugin

Maven plugin for running and creating Docker images
https://dmp.fabric8.io
Apache License 2.0
1.87k stars 643 forks source link

Error pushing to GCR with one-lined JSON key as password #1033

Open seboudry opened 6 years ago

seboudry commented 6 years ago

Description

Hi! Trying to push to GCR with d-m-p using JSON key mechanism. The JSON key is passed to build using an environment variable, so must be a one-line string. DMP fails to decrypt password, it assumes that's a Maven encrypted password (MavenPlexusCipher matches the one-lined JSON with the Maven password regex).

I filled this issue to record it, but don't know if you can handle a fix into d-m-p for this typical use case.

Info

Reproduce bug

Download a JSON key file from a Google service account. Have no issue with using JSON key file directly:

mvn fabric8:push \
  -Ddocker.push.registry=eu.gcr.io/awesome \
  -Ddocker.push.username=_json_key \
  "-Ddocker.push.password=$(cat keyfile.json)"

Make the JSON key file one-line and export it to an env variable:

jq -c . keyfile.json > keyfile-oneline.json
export GCR_JSONKEY=$(cat keyfile-oneline.json)

Try using this env var:

mvn fabric8:push \
  -Ddocker.push.registry=eu.gcr.io/awesome \
  -Ddocker.push.username=_json_key \
  "-Ddocker.push.password=${GCR_JSONKEY}"

Note that f-m-p as no implication in this bug, all Docker authentication is delegated to d-m-p.

[INFO] --- fabric8-maven-plugin:3.5.39:push (default-cli) @ qs-framework-fabric8-python-samples-echo ---
[INFO] F8> Generators:
[INFO] F8>  - spring-boot
[INFO] F8>  - wildfly-swarm
[INFO] F8>  - karaf
[INFO] F8>  - vertx
[INFO] F8>  - java-exec
[INFO] F8>  - webapp
[ERROR] F8> Cannot decrypt password: org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: org.sonatype.plexus.components.cipher.PlexusCipherException: java.lang.ArrayIndexOutOfBoundsException [null]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.554 s
[INFO] Finished at: 2018-05-28T10:51:05+02:00
[INFO] Final Memory: 87M/743M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal io.fabric8:fabric8-maven-plugin:3.5.39:push (default-cli) on project qs-framework-fabric8-python-samples-echo: Cannot decrypt password: org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: org.sonatype.plexus.components.cipher.PlexusCipherException: java.lang.ArrayIndexOutOfBoundsException: InvocationTargetException -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal io.fabric8:fabric8-maven-plugin:3.5.39:push (default-cli) on project qs-framework-fabric8-python-samples-echo: Cannot decrypt password: org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: org.sonatype.plexus.components.cipher.PlexusCipherException: java.lang.ArrayIndexOutOfBoundsException
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:213)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:309)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:194)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:107)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:993)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:345)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:191)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.MojoExecutionException: Cannot decrypt password: org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: org.sonatype.plexus.components.cipher.PlexusCipherException: java.lang.ArrayIndexOutOfBoundsException
    at io.fabric8.maven.docker.util.AuthConfigFactory.decrypt(AuthConfigFactory.java:445)
    at io.fabric8.maven.docker.util.AuthConfigFactory.getAuthConfigFromSystemProperties(AuthConfigFactory.java:232)
    at io.fabric8.maven.docker.util.AuthConfigFactory.createStandardAuthConfig(AuthConfigFactory.java:186)
    at io.fabric8.maven.docker.util.AuthConfigFactory.createAuthConfig(AuthConfigFactory.java:107)
    at io.fabric8.maven.docker.service.RegistryService.createAuthConfig(RegistryService.java:96)
    at io.fabric8.maven.docker.service.RegistryService.pushImages(RegistryService.java:46)
    at io.fabric8.maven.docker.PushMojo.executeInternal(PushMojo.java:38)
    at io.fabric8.maven.docker.AbstractDockerMojo.execute(AbstractDockerMojo.java:223)
    at io.fabric8.maven.plugin.mojo.build.PushMojo.execute(PushMojo.java:101)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
    ... 20 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at io.fabric8.maven.docker.util.AuthConfigFactory.decrypt(AuthConfigFactory.java:441)
    ... 30 more
Caused by: org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: org.sonatype.plexus.components.cipher.PlexusCipherException: java.lang.ArrayIndexOutOfBoundsException
    at org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher.decrypt(DefaultSecDispatcher.java:121)
    ... 35 more
Caused by: org.sonatype.plexus.components.cipher.PlexusCipherException: java.lang.ArrayIndexOutOfBoundsException
    at org.sonatype.plexus.components.cipher.PBECipher.decrypt64(PBECipher.java:193)
    at org.sonatype.plexus.components.cipher.DefaultPlexusCipher.decrypt(DefaultPlexusCipher.java:74)
    at org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher.decrypt(DefaultSecDispatcher.java:96)
    ... 35 more
Caused by: java.lang.ArrayIndexOutOfBoundsException
    at java.lang.System.arraycopy(Native Method)
    at org.sonatype.plexus.components.cipher.PBECipher.decrypt64(PBECipher.java:181)
    ... 37 more
seboudry commented 6 years ago

So, not working the same way on different environments. On my MacOS workstation, Maven consider the given password great, but on Atlassian Bamboo (same Oracle JDK version, same Maven version but Ubuntu) given password is considered as an encrypted text and all Plexus decrypting runs ... and fails.

edit: working in local, but not un Bamboo: cat command is not interpreted :( Only working way: have to use an intermediate multiline JSON file !

printf "%s" "${bamboo.GCR_JSONKEY}" > gcr-keyfile.json
mvn fabric8:push \
  -Ddocker.push.registry=eu.gcr.io/awesome \
  -Ddocker.push.username=_json_key \
  "-Ddocker.push.password=$(cat gcr-keyfile.json)"

Hope this will help anybody

seboudry commented 6 years ago

DMP don't work with GCR auth keyfile, even with the PR https://github.com/fabric8io/docker-maven-plugin/pull/1036 that don't try to apply Maven decryption on JSON key. I think that method io.fabric8.maven.docker.access.AuthConfig#createAuthEncoded isn't adapted for this kind of GCR authentication.

So my workaround is to not use fmp for only pushing images. Use docker login then docker push with same image name calculated by fmp/dmp.

rhuss commented 6 years ago

Sorry for being so unresponsive, lot of things are going on here. We should definitely fix this, so let me reopen this issue.

seboudry commented 6 years ago

Hi, I'm on vacation until begining of jully. Will take a look at this at my return. Cleaner solution might be to use a specific mecanism as for Amazon registry. To not polute existing code.

rhuss commented 6 years ago

@seboudry let me know when we can tackle this issue.

Allsimon commented 6 years ago

A workaround just in case someone else needs it:

mvn fabric8:push  \
    -Ddocker.push.registry=eu.gcr.io/awesome \
    -Ddocker.username=oauth2accesstoken \
    -Ddocker.password=$(gcloud auth print-access-token)
ankurga commented 2 years ago

Was this resolved? I am also facing the same issue with version 0.39.1

[INFO] --- docker-maven-plugin:0.39.1:push (default) @ recon-kafka-retry-service ---
[ERROR] DOCKER> Cannot decrypt password: org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException: java.io.FileNotFoundException: /var/go/.m2/settings-security.xml (No such file or directory) [null]
rhuss commented 2 years ago

@ankurga I don't think this is the same issue. It looks like that Maven can't find your settings.yml.

agustin-eche commented 1 year ago

I am working with DMP but included in a pom.xml, as part of the build process. What comes as input to my maven build is a file path ('sa_credentials_file'), the one of the key.json. That file in my case comes as a oneliner so I did hit the problem described here. What I did is to insert a goal right before DMP to basically make the oneliner not to be a oneliner, by replacing the opening brace '{'by '{' + System.getProperty('line.separator'). I did that with a scriptlet in groovy using gmaven-plugin:

<plugin>
    <groupId>org.codehaus.gmaven</groupId>
    <artifactId>gmaven-plugin</artifactId>
    <version>1.5</version>
    <executions>
        <execution>
    <phase>process-resources</phase>
    <goals>
        <goal>execute</goal>
    </goals>
    <configuration>
        <providerSelection>1.8</providerSelection>
        <source>
            def newline = System.getProperty('line.separator')
            def file = new File(project.properties.sa_credentials_file) // gcp json credentials
            project.properties.sa_credentials = file.getText().replaceFirst('\{', '\{'+newline)
        </source>
    </configuration>
        </execution>
    </executions>
</plugin>

Then I just use that 'sa_credentials' variable created there to configure DMP:

<authConfig>
    <username>_json_key</username>
    <password>${sa_credentials}</password>
</authConfig>

It doesn't have to be groovy, you can take your pick on how to add that extra newline sequence after the opening brace.

TL;DR: By introducing a single newline char|sequence after the opening brace you will make the credentials text 'fall-off' the regex pattern that makes DMP think that it needs to decrypt something. Other edits might work too.