Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request to update documentation regarding - 401 unauthorized #2561

Closed
abitgen opened this issue Jul 1, 2020 · 2 comments
Closed

Request to update documentation regarding - 401 unauthorized #2561

abitgen opened this issue Jul 1, 2020 · 2 comments

Comments

@abitgen
Copy link

abitgen commented Jul 1, 2020

Environment:

  • Jib version: 2.4.0
  • Build tool: Gradle 5.6.1
  • OS: Windows 10 build 2004

Description of the issue:
Not specifying the username in --image parameter results in 401 unauthorized

Steps to reproduce:

Note: I have fixed the issue by adding username before image name , this is more of an enhancement in documentation and logging. check Expected behavior section

jib-gradle-plugin Configuration:

plugins {
    java
    kotlin("jvm")
    kotlin("plugin.spring") version "1.3.72"
    id("org.springframework.boot") version "2.3.1.RELEASE"
    id("io.spring.dependency-management") version "1.0.9.RELEASE"
    id("com.google.cloud.tools.jib")
}

group = "guru.springframework"
version = "1.0-SNAPSHOT"

configure<JavaPluginConvention> {
    sourceCompatibility = JavaVersion.VERSION_1_8
}


repositories {
    jcenter()
}

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    testImplementation(group= "junit", name= "junit", version= "4.12")
    testImplementation("org.junit.jupiter:junit-jupiter:5.6.2")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa:2.3.1.RELEASE")
    implementation("org.springframework.boot:spring-boot-starter-security:2.3.1.RELEASE")
    implementation("org.springframework.boot:spring-boot-starter-thymeleaf:2.3.1.RELEASE")
    implementation("org.springframework.boot:spring-boot-starter-web:2.3.1.RELEASE")
    implementation("org.webjars:bootstrap:4.5.0")
    implementation("org.webjars:jquery:3.5.1")
    implementation("com.h2database:h2:1.4.200")
    testImplementation( "org.springframework.boot:spring-boot-starter-test:2.3.1.RELEASE")
}

tasks {
    compileKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    compileTestKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
}

jib.to.image = "docdodoc/catalogapp"
jib.to.credHelper = "wincred"

Log output:

>gradlew catalogapp:jib --image=catalogapp_docker --stacktrace

> Task :catalogapp:jib

Containerizing application to catalogapp_docker...
Base image 'gcr.io/distroless/java:8' does not use a specific image digest - build may not be reproducible
Using credential helper docker-credential-wincred for catalogapp_docker
Using base image with digest: sha256:7cef6d99241bc86e09659d41842e3656a1cab99adf0e440a44d2858c8e52a71a
I/O error for image [registry-1.docker.io/library/catalogapp_docker]:
    java.net.SocketException
    Socket Closed
I/O error for image [registry-1.docker.io/library/catalogapp_docker]:
    java.net.SocketException
    Socket Closed
I/O error for image [registry-1.docker.io/library/catalogapp_docker]:
    java.net.SocketException
    Socket Closed
I/O error for image [registry-1.docker.io/library/catalogapp_docker]:
    java.net.SocketException
    Socket Closed
I/O error for image [registry-1.docker.io/library/catalogapp_docker]:
    java.net.SocketException
    Socket Closed
Executing tasks:
[================              ] 51.9% complete
> pushing blob sha256:fcc777530ff9a3ae1c14506e2...
> launching layer pushers


> Task :catalogapp:jib FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':catalogapp:jib'.
> com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException: Build image failed, perhaps you should make sure your credentia
ls for 'registry-1.docker.io/library/catalogapp_docker' are set up correctly. See https:/GoogleContainerTools/jib/blob/master
/docs/faq.md#what-should-i-do-when-the-registry-responds-with-unauthorized for help

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':catalogapp:jib'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.accept(ExecuteActionsTaskExecuter.java:166)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.accept(ExecuteActionsTaskExecuter.java:163)
        at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:191)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:156)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:108)
        at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionOutputsTaskExecuter.execute(ResolveBeforeExecutionOutputsTaskExe
cuter.java:67)
        at org.gradle.api.internal.tasks.execution.ResolveAfterPreviousExecutionStateTaskExecuter.execute(ResolveAfterPreviousExecutionSt
ateTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:94)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:95)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecuto
r.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecuto
r.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.
java:336)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.
java:322)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:134)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:129)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:202)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:193)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:129)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
Caused by: org.gradle.internal.UncheckedException: com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException: Build image fa
iled, perhaps you should make sure your credentials for 'registry-1.docker.io/library/catalogapp_docker' are set up correctly. See https:
/GoogleContainerTools/jib/blob/master/docs/faq.md#what-should-i-do-when-the-registry-responds-with-unauthorized for help
        at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:67)
        at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:41)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:106)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:49)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:42)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:717)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:684)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$5.run(ExecuteActionsTaskExecuter.java:476)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecuto
r.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecuto
r.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:461)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:444)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$200(ExecuteActionsTaskExecuter.java:93)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:237)
        at org.gradle.internal.execution.steps.ExecuteStep.lambda$execute$1(ExecuteStep.java:33)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:33)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:26)
        at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:58)
        at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:35)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:48)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:33)
        at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:39)
        at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:73)
        at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:54)
        at org.gradle.internal.execution.steps.CatchExceptionStep.execute(CatchExceptionStep.java:35)
        at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:51)
        at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:45)
        at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:31)
        at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:208)
        at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:70)
        at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:45)
        at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:49)
        at org.gradle.internal.execution.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:43)
        at org.gradle.internal.execution.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:32)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:96)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:89)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:54)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:38)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:76)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:
36)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:
26)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:90)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:48)
        at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:69)
        at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:47)
        at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:140)
        ... 34 more
Caused by: com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException: Build image failed, perhaps you should make sure your
credentials for 'registry-1.docker.io/library/catalogapp_docker' are set up correctly. See https:/GoogleContainerTools/jib/bl
ob/master/docs/faq.md#what-should-i-do-when-the-registry-responds-with-unauthorized for help
        at com.google.cloud.tools.jib.plugins.common.JibBuildRunner.handleRegistryUnauthorizedException(JibBuildRunner.java:181)
        at com.google.cloud.tools.jib.plugins.common.JibBuildRunner.runBuild(JibBuildRunner.java:254)
        at com.google.cloud.tools.jib.gradle.BuildImageTask.buildImage(BuildImageTask.java:111)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:103)
        ... 87 more
Caused by: com.google.cloud.tools.jib.api.RegistryUnauthorizedException: Unauthorized for registry-1.docker.io/library/catalogapp_docker
        at com.google.cloud.tools.jib.registry.RegistryEndpointCaller.call(RegistryEndpointCaller.java:164)
        at com.google.cloud.tools.jib.registry.RegistryEndpointCaller.call(RegistryEndpointCaller.java:115)
        at com.google.cloud.tools.jib.registry.RegistryClient.callRegistryEndpoint(RegistryClient.java:573)
        at com.google.cloud.tools.jib.registry.RegistryClient.checkBlob(RegistryClient.java:425)
        at com.google.cloud.tools.jib.builder.steps.ObtainBaseImageLayerStep.lambda$makeListForSelectiveDownload$1(ObtainBaseImageLayerSt
ep.java:74)
        at com.google.cloud.tools.jib.builder.steps.ObtainBaseImageLayerStep.call(ObtainBaseImageLayerStep.java:142)
        at com.google.cloud.tools.jib.builder.steps.ObtainBaseImageLayerStep.call(ObtainBaseImageLayerStep.java:43)
        at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenabl
eFutureTask.java:125)
        at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:69)
        at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:78)
Caused by: com.google.cloud.tools.jib.http.ResponseException: 401 Unauthorized
        at com.google.cloud.tools.jib.http.FailoverHttpClient.call(FailoverHttpClient.java:323)
        at com.google.cloud.tools.jib.http.FailoverHttpClient.call(FailoverHttpClient.java:244)
        at com.google.cloud.tools.jib.registry.RegistryEndpointCaller.call(RegistryEndpointCaller.java:139)
        ... 9 more
Caused by: com.google.api.client.http.HttpResponseException: 401 Unauthorized
        at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1113)
        at com.google.cloud.tools.jib.http.FailoverHttpClient.call(FailoverHttpClient.java:317)
        ... 11 more


* Get more help at https://help.gradle.org

BUILD FAILED in 43s
4 actionable tasks: 1 executed, 3 up-to-date

Additional Information:

gradlew catalogapp:jib --image=catalogapp_docker --stacktrace Doesnt Work As I didn't pass my username, and this value was overriding my configured image name in gradle

gradlew catalogapp:jib --stacktrace Works Takes the image name value provided in gradle
gradlew catalogapp:jib --image=<USER_NAME>/catalogapp_docker --stacktrace Works

Expected behavior:
The addition of --image argument which overrides the existing value from the jib.to.image should be notified/logged.

In the documentation, it would be better to modify the image command to include the <USER_NAME> field as well.
like this. gradle jib --image=<USER_NAME>/<IMAGE_NAME>

@chanseokoh
Copy link
Member

chanseokoh commented Aug 21, 2020

The image reference determines the server URL of the target registry. In this regard, typing an image reference in Jib is very similar to typing a web server URL in the address bar of a web browser; each server uses different URL paths to access their resources, and it's basically the user's responsibility to know which URL and path to type to access a resource on the server they want.

To clarify, it is not that an image reference must contain a username. catalogapp_docker (i.e., without a username) is still a valid image reference for Docker Hub and is absolutely usable in Jib, as much as openjdk is a valid one. It is just that you don't have enough permission to push an image to the catalogapp_docker, because it is someone else's repository, as much as openjdk is not your repository. Therefore, it is not always correct to suggest to add a username for a Docker Hub image reference; for people maintaining openjdk (and potentially catalogapp_docker), they must not add a username.

However, I think it does make sense to improve our FAQ about 401 unauthorized on this front, because people owning top-level Docker Hub repositories will already know very well what they are doing; only those people inexperienced in Docker will hit this type of hiccup.


More details about image reference format:

Technically, an image reference is completely free-form; you can use whatever format you want (as long as syntactically acceptable), be it helloworld or my/awesome/image. Now, when you want to target a certain registry, an image reference needs to be of the form <registry host>[:<port>]/some/repo/name/.... And additionally, tools in the Docker ecosystem have special support only for Docker Hub that allows you to omit <registry host>[:<port>]. Another interesting thing about Docker Hub is that it doesn't support multi-level repository names.

Examples:

  • localhost:5000/my-repo
  • some.private-company.com/registry/some-namespace/some-repo
  • Google GCR
    • gcr.io/<PROJECT ID>/some/repo/hierarchy
    • gcr.io/<ORGANIZATION>/<PROJECT ID>/...
    • ...
  • Amazon ECR
    • <AWS ACCOUNT ID>.dkr.ecr.<REGION>.amazonaws.com/my-repo
    • <AWS ACCOUNT ID>.dkr.ecr.<REGION>.amazonaws.com/<NAMESPACE>/my-repo
    • ...
  • Docker Hub
    • For usual people:
      • Most common: <ACCOUNT NAME>/my-repo (special Docker Hub-only support), e.g., azul/zulu-openjdk
      • Less common (some of them are symbolic aliases and may work only in some tools that interpret them):
        • registry-1.docker.io/<ACCOUNT_NAME>/repo
        • registry.hub.docker.com/<ACCOUNT_NAME>/repo
        • index.docker.io/<ACCOUNT_NAME>/repo
        • docker.io/<ACCOUNT_NAME>/repo
        • ...
      • WRONG: <ACCOUNT NAME>/my-repo/another-level (Docker Hub doesn't support multi-level names)
    • For certain people maintaining "official" (top-level) Docker Hub repositories:
      • Most common: repo (special Docker Hub-only support), e.g., openjdk.
      • Less common (some of them are symbolic aliases and may work only in some tools that interpret them):
        • registry-1.docker.io/repo
        • registry.hub.docker.com/repo
        • index.docker.io/repo
        • docker.io/repo
        • ...

@chanseokoh
Copy link
Member

Forgot to close this back then. I think there's no need to update the code or doc. The user misunderstanding was the source of the confusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants