Merge pull request #1928 from ghostplant/master
Dynamically Parsing the Latest HTPassword Filemaster
						commit
						41f383fb9a
					
				|  | @ -9,6 +9,8 @@ import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"sync" | ||||||
|  | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/docker/distribution/context" | 	"github.com/docker/distribution/context" | ||||||
| 	"github.com/docker/distribution/registry/auth" | 	"github.com/docker/distribution/registry/auth" | ||||||
|  | @ -16,6 +18,9 @@ import ( | ||||||
| 
 | 
 | ||||||
| type accessController struct { | type accessController struct { | ||||||
| 	realm    string | 	realm    string | ||||||
|  | 	path     string | ||||||
|  | 	modtime  time.Time | ||||||
|  | 	mu       sync.Mutex | ||||||
| 	htpasswd *htpasswd | 	htpasswd *htpasswd | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -32,18 +37,7 @@ func newAccessController(options map[string]interface{}) (auth.AccessController, | ||||||
| 		return nil, fmt.Errorf(`"path" must be set for htpasswd access controller`) | 		return nil, fmt.Errorf(`"path" must be set for htpasswd access controller`) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	f, err := os.Open(path.(string)) | 	return &accessController{realm: realm.(string), path: path.(string)}, nil | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	defer f.Close() |  | ||||||
| 
 |  | ||||||
| 	h, err := newHTPasswd(f) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return &accessController{realm: realm.(string), htpasswd: h}, nil |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ac *accessController) Authorized(ctx context.Context, accessRecords ...auth.Access) (context.Context, error) { | func (ac *accessController) Authorized(ctx context.Context, accessRecords ...auth.Access) (context.Context, error) { | ||||||
|  | @ -60,7 +54,35 @@ func (ac *accessController) Authorized(ctx context.Context, accessRecords ...aut | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if err := ac.AuthenticateUser(username, password); err != nil { | 	// Dynamically parsing the latest account list
 | ||||||
|  | 	fstat, err := os.Stat(ac.path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lastModified := fstat.ModTime() | ||||||
|  | 	ac.mu.Lock() | ||||||
|  | 	if ac.htpasswd == nil || !ac.modtime.Equal(lastModified) { | ||||||
|  | 		ac.modtime = lastModified | ||||||
|  | 
 | ||||||
|  | 		f, err := os.Open(ac.path) | ||||||
|  | 		if err != nil { | ||||||
|  | 			ac.mu.Unlock() | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		defer f.Close() | ||||||
|  | 
 | ||||||
|  | 		h, err := newHTPasswd(f) | ||||||
|  | 		if err != nil { | ||||||
|  | 			ac.mu.Unlock() | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		ac.htpasswd = h | ||||||
|  | 	} | ||||||
|  | 	localHTPasswd := ac.htpasswd | ||||||
|  | 	ac.mu.Unlock() | ||||||
|  | 
 | ||||||
|  | 	if err := localHTPasswd.authenticateUser(username, password); err != nil { | ||||||
| 		context.GetLogger(ctx).Errorf("error authenticating user %q: %v", username, err) | 		context.GetLogger(ctx).Errorf("error authenticating user %q: %v", username, err) | ||||||
| 		return nil, &challenge{ | 		return nil, &challenge{ | ||||||
| 			realm: ac.realm, | 			realm: ac.realm, | ||||||
|  | @ -71,10 +93,6 @@ func (ac *accessController) Authorized(ctx context.Context, accessRecords ...aut | ||||||
| 	return auth.WithUser(ctx, auth.UserInfo{Name: username}), nil | 	return auth.WithUser(ctx, auth.UserInfo{Name: username}), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ac *accessController) AuthenticateUser(username, password string) error { |  | ||||||
| 	return ac.htpasswd.authenticateUser(username, password) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // challenge implements the auth.Challenge interface.
 | // challenge implements the auth.Challenge interface.
 | ||||||
| type challenge struct { | type challenge struct { | ||||||
| 	realm string | 	realm string | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue