working commit

This commit is contained in:
2026-02-17 19:24:29 +02:00
parent b76ea1a9ac
commit 8739f2feb7
18 changed files with 1702 additions and 756 deletions
+30 -19
View File
@@ -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
}
+8 -2
View File
@@ -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)
-1
View File
@@ -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"`)
+14
View File
@@ -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 -6
View File
@@ -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)
+2 -2
View File
@@ -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)