working commit
This commit is contained in:
+30
-19
@@ -29,12 +29,12 @@ func (hand *Handler) AuthMiddleware(next router.Handler) router.Handler {
|
||||
var handlerFunc router.HandlerFunc
|
||||
|
||||
handlerFunc = func(rctx *router.Context) {
|
||||
hand.logg.Debugf("Call authorization middleware")
|
||||
//hand.logg.Debugf("Call authorization middleware")
|
||||
success, accountID, err := hand.CheckAccess(rctx)
|
||||
if success {
|
||||
rctx.SetBool(authTag, true)
|
||||
rctx.SetString(userTag, accountID)
|
||||
hand.logg.Debugf("Authorization for accountID [%s]", rctx.Strings[userTag])
|
||||
//hand.logg.Debugf("Authorization for accountID [%s]", rctx.Strings[userTag])
|
||||
}
|
||||
if err != nil {
|
||||
hand.logg.Errorf("Authorization middleware error: %v", err)
|
||||
@@ -45,6 +45,7 @@ func (hand *Handler) AuthMiddleware(next router.Handler) router.Handler {
|
||||
return handlerFunc
|
||||
}
|
||||
|
||||
// Authentification
|
||||
func (hand *Handler) CheckAccess(rctx *router.Context) (bool, string, error) {
|
||||
var err error
|
||||
var success bool
|
||||
@@ -56,12 +57,15 @@ func (hand *Handler) CheckAccess(rctx *router.Context) (bool, string, error) {
|
||||
|
||||
authHeader := rctx.GetHeader("Authorization")
|
||||
if authHeader != "" {
|
||||
hand.logg.Debugf("Authorization header is %s", authHeader)
|
||||
//hand.logg.Debugf("Authorization header is %s", authHeader)
|
||||
username, password, err = auxhttp.ParseBasicAuth(authHeader)
|
||||
if err != nil {
|
||||
return success, accountID, err
|
||||
}
|
||||
hand.logg.Debugf("Authorization pair is %s:%s", username, password)
|
||||
//hand.logg.Debugf("Authorization pair is %s:%s", username, password)
|
||||
if username == "" || password == "" {
|
||||
goto anonymous
|
||||
}
|
||||
|
||||
success, id, err := hand.ValidatePassword(rctx.Ctx, username, password)
|
||||
if err != nil {
|
||||
@@ -74,6 +78,7 @@ func (hand *Handler) CheckAccess(rctx *router.Context) (bool, string, error) {
|
||||
accountID = id
|
||||
return success, accountID, err
|
||||
}
|
||||
anonymous:
|
||||
success = true
|
||||
accountID = descr.AnonymousID
|
||||
return success, accountID, err
|
||||
@@ -99,38 +104,44 @@ func (hand *Handler) ValidatePassword(ctx context.Context, username, password st
|
||||
return valid, accountID, err
|
||||
}
|
||||
|
||||
func (hand *Handler) CheckRight(ctx context.Context, accountID, right, subject string) (bool, error) {
|
||||
// Authorization
|
||||
|
||||
func (hand *Handler) CheckRight(ctx context.Context, accountID, reqRight, subject string) (bool, error) {
|
||||
var err error
|
||||
var res bool
|
||||
hand.logg.Debugf("Cop check your right %s: %s %s", accountID, right, subject)
|
||||
//hand.logg.Debugf("Cop check your right %s: %s %s", accountID, reqRight, subject)
|
||||
// =[]=
|
||||
// .------.
|
||||
// .---[-] [#] \--,
|
||||
// >| [ ] [ ] |
|
||||
// .------. ---
|
||||
// .---[-] [#] \--, ---
|
||||
// >| [ ] [ ] | ---...
|
||||
// '--0-------0----'
|
||||
// Bad news for you, baby.... #
|
||||
//
|
||||
exists, grant, err := hand.mdb.GetGrantByAccoundIDRight(ctx, accountID, right)
|
||||
exists, grants, err := hand.mdb.ListGrantsByAccoundIDRight(ctx, accountID, reqRight)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if !exists {
|
||||
return res, err
|
||||
}
|
||||
switch right {
|
||||
switch reqRight {
|
||||
case descr.RightReadFiles, descr.RightWriteFiles:
|
||||
grant.Pattern = ".*"
|
||||
re, err := regexp.Compile(grant.Pattern)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if !re.MatchString(subject) {
|
||||
return res, err
|
||||
for _, grant := range grants {
|
||||
re, err := regexp.Compile(grant.Pattern)
|
||||
if err != nil {
|
||||
hand.logg.Warningf("Wrong pattern %s for grant %s: %v", grant.Pattern, grant.ID, err)
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
if re.MatchString(subject) {
|
||||
res = true
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
// NOP
|
||||
}
|
||||
res = true
|
||||
hand.logg.Debugf("Checking right %s for %s: %v", right, accountID, res)
|
||||
//hand.logg.Debugf("Result of checking right %s for %s: %v", reqRight, accountID, res)
|
||||
return res, err
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ func (hand *Handler) ManifestExists(rctx *router.Context) {
|
||||
name, _ := rctx.GetSubpath("name")
|
||||
reference, _ := rctx.GetSubpath("reference")
|
||||
|
||||
hand.DumpHeaders("ManigestExists:\n", rctx)
|
||||
|
||||
params := &operator.ManifestExistsParams{
|
||||
Name: name,
|
||||
Reference: reference,
|
||||
@@ -94,6 +96,8 @@ func (hand *Handler) GetManifest(rctx *router.Context) {
|
||||
name, _ := rctx.GetSubpath("name")
|
||||
reference, _ := rctx.GetSubpath("reference")
|
||||
|
||||
//hand.DumpHeaders("GetManigest", rctx)
|
||||
|
||||
params := &operator.GetManifestParams{
|
||||
Name: name,
|
||||
Reference: reference,
|
||||
@@ -118,10 +122,12 @@ func (hand *Handler) GetManifest(rctx *router.Context) {
|
||||
return
|
||||
}
|
||||
if code == http.StatusOK {
|
||||
//hand.logg.Debugf("GetManifest type: %s", res.ContentType)
|
||||
//hand.logg.Debugf("GetManifest payload: %s", res.Payload)
|
||||
rctx.SetHeader("Content-Length", res.ContentLength)
|
||||
rctx.SetHeader("Content-Type", res.ContentType)
|
||||
//rctx.SetHeader("Content-Type", res.ContentType)
|
||||
rctx.SetHeader("Docker-Content-Digest", res.DockerContentDigest)
|
||||
rctx.SendBytes(code, []byte(res.Payload))
|
||||
rctx.SendBytes(code, res.ContentType, []byte(res.Payload))
|
||||
return
|
||||
}
|
||||
rctx.SetStatus(code)
|
||||
|
||||
@@ -21,7 +21,6 @@ func (hand *Handler) GetVersion(rctx *router.Context) {
|
||||
params := &operator.GetVersionParams{}
|
||||
|
||||
//hand.DumpHeaders("GetVersion", rctx)
|
||||
|
||||
authorization := rctx.GetHeader("Authorization")
|
||||
if authorization == "" {
|
||||
rctx.SetHeader("WWW-Authenticate", `Basic realm="mstore"`)
|
||||
|
||||
@@ -93,6 +93,20 @@ func (db *Database) GetGrantByAccoundIDRight(ctx context.Context, accountID, rig
|
||||
return true, res, err
|
||||
}
|
||||
|
||||
func (db *Database) ListGrantsByAccoundIDRight(ctx context.Context, accountID, right string) (bool, []descr.Grant, error) {
|
||||
var err error
|
||||
request := `SELECT * FROM grants WHERE account_id = $1 AND right = $2`
|
||||
res := make([]descr.Grant, 0)
|
||||
err = db.db.Select(&res, request, accountID, right)
|
||||
if err != nil {
|
||||
return false, res, err
|
||||
}
|
||||
if len(res) == 0 {
|
||||
return false, res, err
|
||||
}
|
||||
return true, res, err
|
||||
}
|
||||
|
||||
func (db *Database) GetGrantByAccoundIDRightPattern(ctx context.Context, accountID, right, pattern string) (bool, *descr.Grant, error) {
|
||||
var err error
|
||||
res := &descr.Grant{}
|
||||
|
||||
@@ -22,11 +22,6 @@ import (
|
||||
"mstore/pkg/auxoci"
|
||||
)
|
||||
|
||||
const (
|
||||
ddmMimeType = "application/vnd.docker.distribution.manifest.v2+json"
|
||||
oimMimeType = "application/vnd.oci.image.manifest.v1+json"
|
||||
)
|
||||
|
||||
type ManifestExistsParams struct {
|
||||
Name string
|
||||
Reference string
|
||||
@@ -93,6 +88,14 @@ type PutManifestResult struct {
|
||||
Location string
|
||||
}
|
||||
|
||||
const (
|
||||
ddmMimeType = "application/vnd.docker.distribution.manifest.v2+json"
|
||||
oimMimeType = "application/vnd.oci.image.manifest.v1+json"
|
||||
|
||||
oicMimeType = "application/vnd.oci.image.config.v1+json"
|
||||
dciMimeType = "application/vnd.docker.container.image.v1+json"
|
||||
)
|
||||
|
||||
// TODO: lock for the name-reference or simular?
|
||||
func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams) (*PutManifestResult, int, error) {
|
||||
var err error
|
||||
@@ -107,7 +110,12 @@ func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams
|
||||
return res, http.StatusBadRequest, err
|
||||
}
|
||||
// Check Content-Type
|
||||
if params.ContentType != oimMimeType {
|
||||
var mimeIsAcceptably bool
|
||||
mimeIsAcceptably = mimeIsAcceptably || params.ContentType == oimMimeType
|
||||
mimeIsAcceptably = mimeIsAcceptably || params.ContentType == ddmMimeType
|
||||
mimeIsAcceptably = mimeIsAcceptably || params.ContentType == oicMimeType
|
||||
mimeIsAcceptably = mimeIsAcceptably || params.ContentType == dciMimeType
|
||||
if !mimeIsAcceptably {
|
||||
err = fmt.Errorf("Unknown or empty Content-Type: %s", params.ContentType)
|
||||
return res, http.StatusNotFound, err
|
||||
}
|
||||
@@ -143,6 +151,14 @@ func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams
|
||||
code := http.StatusRequestEntityTooLarge
|
||||
return res, code, err
|
||||
}
|
||||
|
||||
// Check point
|
||||
oper.logg.Debugf("=== Incoming manifest type: %s", params.ContentType)
|
||||
oper.logg.Debugf("=== Incoming manifest body: %s", string(incomingManifestBytes))
|
||||
if params.ContentType == oicMimeType || params.ContentType == dciMimeType {
|
||||
return res, http.StatusOK, err
|
||||
}
|
||||
|
||||
incomingManifest, err := auxoci.ParseOCIManifest(incomingManifestBytes)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Parsing OCI manifest error: %v", err)
|
||||
|
||||
@@ -142,9 +142,9 @@ func (rctx *Context) SendText(statusCode int, payload string) {
|
||||
rctx.Writer.Write([]byte(payload))
|
||||
}
|
||||
|
||||
func (rctx *Context) SendBytes(statusCode int, payload []byte) {
|
||||
func (rctx *Context) SendBytes(statusCode int, ctype string, payload []byte) {
|
||||
size := strconv.FormatInt(int64(len(payload)), 10)
|
||||
rctx.Writer.Header().Set("Content-Type", "application/octet-stream")
|
||||
rctx.Writer.Header().Set("Content-Type", ctype)
|
||||
rctx.Writer.Header().Set("Content-Length", size)
|
||||
rctx.Writer.WriteHeader(statusCode)
|
||||
rctx.Writer.Write(payload)
|
||||
|
||||
Reference in New Issue
Block a user