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

add /auth for docker compatibility #9589

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions pkg/api/handlers/compat/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package compat

import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"

DockerClient "github.com/containers/image/v5/docker"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/registries"
docker "github.com/docker/docker/api/types"
"github.com/pkg/errors"
)

func stripAddressOfScheme(address string) string {
for _, s := range []string{"https", "http"} {
address = strings.TrimPrefix(address, s+"://")
}
return address
}

func Auth(w http.ResponseWriter, r *http.Request) {
var authConfig docker.AuthConfig
err := json.NewDecoder(r.Body).Decode(&authConfig)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse request"))
return
}

skipTLS := types.NewOptionalBool(false)
if strings.HasPrefix(authConfig.ServerAddress, "https://localhost/") || strings.HasPrefix(authConfig.ServerAddress, "https://localhost:") || strings.HasPrefix(authConfig.ServerAddress, "localhost:") {
// support for local testing
skipTLS = types.NewOptionalBool(true)
}

fmt.Println("Authenticating with existing credentials...")
sysCtx := types.SystemContext{
AuthFilePath: "",
DockerCertPath: "",
DockerInsecureSkipTLSVerify: skipTLS,
SystemRegistriesConfPath: registries.SystemRegistriesConfPath(),
}
registry := stripAddressOfScheme(authConfig.ServerAddress)
if err := DockerClient.CheckAuth(context.Background(), &sysCtx, authConfig.Username, authConfig.Password, registry); err == nil {
utils.WriteResponse(w, http.StatusOK, entities.AuthReport{
IdentityToken: "",
Status: "Login Succeeded",
})
} else {
utils.WriteResponse(w, http.StatusBadRequest, entities.AuthReport{
IdentityToken: "",
Status: "login attempt to " + authConfig.ServerAddress + " failed with status: " + err.Error(),
})
}
}
24 changes: 22 additions & 2 deletions pkg/api/server/register_auth.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
package server

import (
"net/http"

"github.com/containers/podman/v3/pkg/api/handlers/compat"
"github.com/gorilla/mux"
)

func (s *APIServer) registerAuthHandlers(r *mux.Router) error {
r.Handle(VersionedPath("/auth"), s.APIHandler(compat.UnsupportedHandler))
// swagger:operation POST /auth compat auth
// ---
// summary: Check auth configuration
// tags:
// - system (compat)
// produces:
// - application/json
// parameters:
// - in: body
// name: authConfig
// description: Authentication to check
// schema:
// $ref: "#/definitions/AuthConfig"
// responses:
// 200:
// $ref: "#/responses/SystemAuthResponse"
// 500:
// $ref: "#/responses/InternalError"
r.Handle(VersionedPath("/auth"), s.APIHandler(compat.Auth)).Methods(http.MethodPost)
// Added non version path to URI to support docker non versioned paths
r.Handle("/auth", s.APIHandler(compat.UnsupportedHandler))
r.Handle("/auth", s.APIHandler(compat.Auth)).Methods(http.MethodPost)
return nil
}
9 changes: 9 additions & 0 deletions pkg/api/server/swagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,12 @@ type swagSystemPruneReport struct {
entities.SystemPruneReport
}
}

// Auth response
// swagger:response SystemAuthResponse
type swagSystemAuthResponse struct {
// in:body
Body struct {
entities.AuthReport
}
}
11 changes: 11 additions & 0 deletions pkg/domain/entities/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,14 @@ type ComponentVersion struct {
type ListRegistriesReport struct {
Registries []string
}

// swagger:model AuthConfig
type AuthConfig struct {
types.AuthConfig
}

// AuthReport describes the response for authentication check
type AuthReport struct {
IdentityToken string
Status string
}
24 changes: 9 additions & 15 deletions test/apiv2/60-auth.at
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,19 @@

start_registry

# FIXME FIXME FIXME: remove the 'if false' for use with PR 9589
if false; then

# FIXME FIXME: please forgive the horrible POST params format; I have an
# upcoming PR which should fix that.

# Test with wrong password. Confirm bad status and appropriate error message
t POST /v1.40/auth "\"username\":\"${REGISTRY_USERNAME}\",\"password\":\"WrOnGPassWord\",\"serveraddress\":\"localhost:$REGISTRY_PORT/\"" \
t POST /v1.40/auth username=$REGISTRY_USERNAME password=WrOnGPassWord serveraddress=localhost:$REGISTRY_PORT/ \
400 \
.Status~'.* invalid username/password'

# Test with the right password. Confirm status message and reasonable token
t POST /v1.40/auth "\"username\":\"${REGISTRY_USERNAME}\",\"password\":\"${REGISTRY_PASSWORD}\",\"serveraddress\":\"localhost:$REGISTRY_PORT/\"" \
# Test with the right password. Confirm status message
t POST /v1.40/auth username=$REGISTRY_USERNAME password=$REGISTRY_PASSWORD serveraddress=localhost:$REGISTRY_PORT/ \
200 \
.Status="Login Succeeded" \
.IdentityToken~[a-zA-Z0-9]

# FIXME: now what? Try something-something using that token?
token=$(jq -r .IdentityToken <<<"$output")
# ...
.IdentityToken=""

fi # FIXME FIXME FIXME: remove when working
# Same test with url scheme provided
t POST /v1.40/auth username=$REGISTRY_USERNAME password=$REGISTRY_PASSWORD serveraddress=https://localhost:$REGISTRY_PORT/ \
200 \
.Status="Login Succeeded" \
.IdentityToken=""
11 changes: 0 additions & 11 deletions test/apiv2/rest_api/test_rest_v2_0_0.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,17 +555,6 @@ def test_volumes_compat(self):
self.assertIn(name, payload["VolumesDeleted"])
self.assertGreater(payload["SpaceReclaimed"], 0)

def test_auth_compat(self):
r = requests.post(
PODMAN_URL + "/v1.40/auth",
json={
"username": "bozo",
"password": "wedontneednopasswords",
"serveraddress": "https://localhost/v1.40/",
},
)
self.assertEqual(r.status_code, 404, r.content)

def test_version(self):
r = requests.get(PODMAN_URL + "/v1.40/version")
self.assertEqual(r.status_code, 200, r.content)
Expand Down