Skip to content

Commit

Permalink
Temporarily disable v2 registry user auth
Browse files Browse the repository at this point in the history
Use the registry's identity for the SAR check for access to the image
stream.
  • Loading branch information
Andy Goldstein committed Apr 16, 2015
1 parent 3736115 commit b9d98eb
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 70 deletions.
6 changes: 5 additions & 1 deletion hack/test-end-to-end.sh
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,11 @@ osc project cache
token=$(osc config view --flatten -o template -t '{{range .users}}{{if eq .name "e2e-user"}}{{.user.token}}{{end}}{{end}}')
[[ -n ${token} ]]

docker login -u e2e-user -p ${token} -e e2e-user@openshift.com ${DOCKER_REGISTRY}
# TODO reenable this once we've got docker push secrets 100% ready
#docker login -u e2e-user -p ${token} -e e2e-user@openshift.com ${DOCKER_REGISTRY}
# TODO remove the following line once we've got docker push secrets 100% ready
echo '{"apiVersion": "v1beta1", "kind": "ImageStream", "metadata": {"name": "ruby-20-centos7"}}' | osc create -f -

docker tag -f openshift/ruby-20-centos7:latest ${DOCKER_REGISTRY}/cache/ruby-20-centos7:latest
docker push ${DOCKER_REGISTRY}/cache/ruby-20-centos7:latest
echo "[INFO] Pushed ruby-20-centos7"
Expand Down
2 changes: 1 addition & 1 deletion images/dockerregistry/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM openshift/origin-base
ADD config.yml /config.yml
ADD bin/dockerregistry /dockerregistry

ENV REGISTRY_CONFIGURATION_PATH=/config.yml
ENV REGISTRY_CONFIGURATION_PATH=/config.yml DISABLE_USER_AUTH=true

EXPOSE 5000
VOLUME /registry
Expand Down
8 changes: 8 additions & 0 deletions pkg/cmd/server/bootstrappolicy/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ func GetBootstrapMasterRoles(masterNamespace string) []authorizationapi.Role {
Verbs: util.NewStringSet("get", "delete"),
Resources: util.NewStringSet("images"),
},
{
Verbs: util.NewStringSet("get"),
Resources: util.NewStringSet("imagestreamimages", "imagestreamtags", "imagestreams"),
},
{
Verbs: util.NewStringSet("update"),
Resources: util.NewStringSet("imagestreams"),
},
{
Verbs: util.NewStringSet("create"),
Resources: util.NewStringSet("imagerepositorymappings", "imagestreammappings"),
Expand Down
108 changes: 60 additions & 48 deletions pkg/dockerregistry/server/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import (
"errors"
"fmt"
"net/http"
"os"
"strings"

log "github.com/Sirupsen/logrus"
ctxu "github.com/docker/distribution/context"
registryauth "github.com/docker/distribution/registry/auth"
authorizationapi "github.com/openshift/origin/pkg/authorization/api"
"github.com/openshift/origin/pkg/client"
"golang.org/x/net/context"
)

Expand All @@ -20,15 +22,15 @@ func init() {

type contextKey int

var bearerTokenKey contextKey = 0
var userClientKey contextKey = 0

func WithBearerToken(parent context.Context, bearerToken string) context.Context {
return context.WithValue(parent, bearerTokenKey, bearerToken)
func WithUserClient(parent context.Context, userClient *client.Client) context.Context {
return context.WithValue(parent, userClientKey, userClient)
}

func BearerTokenFrom(ctx context.Context) (string, bool) {
bearerToken, ok := ctx.Value(bearerTokenKey).(string)
return bearerToken, ok
func UserClientFrom(ctx context.Context) (*client.Client, bool) {
userClient, ok := ctx.Value(userClientKey).(*client.Client)
return userClient, ok
}

type AccessController struct {
Expand Down Expand Up @@ -84,40 +86,58 @@ func (ac *authChallenge) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Authorized handles checking whether the given request is authorized
// for actions on resources allowed by openshift.
func (ac *AccessController) Authorized(ctx context.Context, accessRecords ...registryauth.Access) (context.Context, error) {
req, err := ctxu.GetRequest(ctx)
if err != nil {
return nil, err
}
var (
client *client.Client
err error
)

challenge := &authChallenge{realm: ac.realm}

authParts := strings.SplitN(req.Header.Get("Authorization"), " ", 2)
if len(authParts) != 2 || strings.ToLower(authParts[0]) != "basic" {
challenge.err = ErrTokenRequired
return nil, challenge
}
basicToken := authParts[1]
if os.Getenv("DISABLE_USER_AUTH") == "true" {
client, err = NewRegistryOpenShiftClient()
if err != nil {
return nil, err
}
} else {
req, err := ctxu.GetRequest(ctx)
if err != nil {
return nil, err
}

payload, err := base64.StdEncoding.DecodeString(basicToken)
if err != nil {
log.Errorf("Basic token decode failed: %s", err)
challenge.err = ErrTokenInvalid
return nil, challenge
}
osAuthParts := strings.SplitN(string(payload), ":", 2)
if len(osAuthParts) != 2 {
challenge.err = ErrOpenShiftTokenRequired
return nil, challenge
}
user := osAuthParts[0]
bearerToken := osAuthParts[1]
authParts := strings.SplitN(req.Header.Get("Authorization"), " ", 2)
if len(authParts) != 2 || strings.ToLower(authParts[0]) != "basic" {
challenge.err = ErrTokenRequired
return nil, challenge
}
basicToken := authParts[1]

// In case of docker login, hits endpoint /v2
if len(accessRecords) == 0 {
err = VerifyOpenShiftUser(user, bearerToken)
payload, err := base64.StdEncoding.DecodeString(basicToken)
if err != nil {
challenge.err = err
log.Errorf("Basic token decode failed: %s", err)
challenge.err = ErrTokenInvalid
return nil, challenge
}
osAuthParts := strings.SplitN(string(payload), ":", 2)
if len(osAuthParts) != 2 {
challenge.err = ErrOpenShiftTokenRequired
return nil, challenge
}
user := osAuthParts[0]
bearerToken := osAuthParts[1]

client, err = NewUserOpenShiftClient(bearerToken)
if err != nil {
return nil, err
}

// In case of docker login, hits endpoint /v2
if len(accessRecords) == 0 {
err = VerifyOpenShiftUser(user, client)
if err != nil {
challenge.err = err
return nil, challenge
}
}
}

for _, access := range accessRecords {
Expand All @@ -136,45 +156,37 @@ func (ac *AccessController) Authorized(ctx context.Context, accessRecords ...reg
verb := ""
switch access.Action {
case "push":
verb = "create"
verb = "update"
case "pull":
verb = "get"
default:
challenge.err = fmt.Errorf("Unkown action: %s", access.Action)
challenge.err = fmt.Errorf("Unknown action: %s", access.Action)
return nil, challenge
}

err = VerifyOpenShiftAccess(repoParts[0], repoParts[1], verb, bearerToken)
err = VerifyOpenShiftAccess(repoParts[0], repoParts[1], verb, client)
if err != nil {
challenge.err = err
return nil, challenge
}
}
return WithBearerToken(ctx, bearerToken), nil
return WithUserClient(ctx, client), nil
}

func VerifyOpenShiftUser(user, bearerToken string) error {
client, err := NewUserOpenShiftClient(bearerToken)
if err != nil {
return err
}
func VerifyOpenShiftUser(user string, client *client.Client) error {
userObj, err := client.Users().Get("~")
if err != nil {
log.Errorf("Get user failed with error: %s", err)
return ErrOpenShiftAccessDenied
}
if user != userObj.ObjectMeta.Name {
if user != userObj.Name {
log.Errorf("Token valid but user name mismatch")
return ErrOpenShiftAccessDenied
}
return nil
}

func VerifyOpenShiftAccess(namespace, imageRepo, verb, bearerToken string) error {
client, err := NewUserOpenShiftClient(bearerToken)
if err != nil {
return err
}
func VerifyOpenShiftAccess(namespace, imageRepo, verb string, client *client.Client) error {
sar := authorizationapi.SubjectAccessReview{
Verb: verb,
Resource: "imageStreams",
Expand Down
32 changes: 12 additions & 20 deletions pkg/dockerregistry/server/repositorymiddleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,9 @@ func (r *repository) Put(ctx context.Context, manifest *manifest.SignedManifest)
},
}

client, err := getUserOpenShiftClient(ctx)
if err != nil {
log.Errorf("Error creating user client to auto provision image stream: %s", err)
client, ok := UserClientFrom(ctx)
if !ok {
log.Errorf("Error creating user client to auto provision image stream: OpenShift user client unavailable")
return statusErr
}

Expand Down Expand Up @@ -250,9 +250,9 @@ func (r *repository) Delete(ctx context.Context, dgst digest.Digest) error {

// getImageStream retrieves the ImageStream for r.
func (r *repository) getImageStream(ctx context.Context) (*imageapi.ImageStream, error) {
client, err := getUserOpenShiftClient(ctx)
if err != nil {
return nil, err
client, ok := UserClientFrom(ctx)
if !ok {
return nil, fmt.Errorf("Error retrieving image stream: OpenShift user client unavailable")
}
return client.ImageStreams(r.namespace).Get(r.name)
}
Expand All @@ -267,19 +267,19 @@ func (r *repository) getImage(dgst digest.Digest) (*imageapi.Image, error) {
// getImageStreamTag retrieves the Image with tag `tag` for the ImageStream
// associated with r.
func (r *repository) getImageStreamTag(ctx context.Context, tag string) (*imageapi.ImageStreamTag, error) {
client, err := getUserOpenShiftClient(ctx)
if err != nil {
return nil, err
client, ok := UserClientFrom(ctx)
if !ok {
return nil, fmt.Errorf("Error retrieving image stream tag: OpenShift user client unavailable")
}
return client.ImageStreamTags(r.namespace).Get(r.name, tag)
}

// getImageStreamImage retrieves the Image with digest `dgst` for the ImageStream
// associated with r. This ensures the user has access to the image.
func (r *repository) getImageStreamImage(ctx context.Context, dgst digest.Digest) (*imageapi.ImageStreamImage, error) {
client, err := getUserOpenShiftClient(ctx)
if err != nil {
return nil, err
client, ok := UserClientFrom(ctx)
if !ok {
return nil, fmt.Errorf("Error retrieving image stream image: OpenShift user client unavailable")
}
return client.ImageStreamImages(r.namespace).Get(r.name, dgst.String())
}
Expand Down Expand Up @@ -314,11 +314,3 @@ func (r *repository) manifestFromImage(image *imageapi.Image) (*manifest.SignedM
}
return &sm, err
}

func getUserOpenShiftClient(ctx context.Context) (*client.Client, error) {
bearerToken, ok := BearerTokenFrom(ctx)
if !ok {
return nil, errors.New("unable to create user OpenShift client: bearer token missing")
}
return NewUserOpenShiftClient(bearerToken)
}

0 comments on commit b9d98eb

Please sign in to comment.