swift: fix crash on bad authentication - fixes #1919

This also fixes Hubic not re-authenticating for long transfers.
This commit is contained in:
Nick Craig-Wood 2017-12-14 14:23:55 +00:00
parent 240c97cd7a
commit 4c0e2f9b3b
2 changed files with 69 additions and 25 deletions

View File

@ -1,29 +1,76 @@
package swift package swift
import "github.com/ncw/swift" import (
"net/http"
// auth is an authenticator for swift "github.com/ncw/swift"
)
// auth is an authenticator for swift. It overrides the StorageUrl
// and AuthToken with fixed values.
type auth struct { type auth struct {
swift.Authenticator parentAuth swift.Authenticator
storageURL string storageURL string
authToken string
} }
// newAuth creates a swift authenticator wrapper to override the // newAuth creates a swift authenticator wrapper to override the
// StorageUrl method. // StorageUrl and AuthToken values.
func newAuth(Authenticator swift.Authenticator, storageURL string) *auth { //
// Note that parentAuth can be nil
func newAuth(parentAuth swift.Authenticator, storageURL string, authToken string) *auth {
return &auth{ return &auth{
Authenticator: Authenticator, parentAuth: parentAuth,
storageURL: storageURL, storageURL: storageURL,
authToken: authToken,
} }
} }
// Request creates an http.Request for the auth - return nil if not needed
func (a *auth) Request(c *swift.Connection) (*http.Request, error) {
if a.parentAuth == nil {
return nil, nil
}
return a.parentAuth.Request(c)
}
// Response parses the http.Response
func (a *auth) Response(resp *http.Response) error {
if a.parentAuth == nil {
return nil
}
return a.parentAuth.Response(resp)
}
// The public storage URL - set Internal to true to read // The public storage URL - set Internal to true to read
// internal/service net URL // internal/service net URL
func (a *auth) StorageUrl(Internal bool) string { func (a *auth) StorageUrl(Internal bool) string {
if a.storageURL != "" { if a.storageURL != "" {
return a.storageURL return a.storageURL
} }
return a.Authenticator.StorageUrl(Internal) if a.parentAuth == nil {
return ""
}
return a.parentAuth.StorageUrl(Internal)
}
// The access token
func (a *auth) Token() string {
if a.authToken != "" {
return a.authToken
}
if a.parentAuth == nil {
return ""
}
return a.parentAuth.Token()
}
// The CDN url if available
func (a *auth) CdnUrl() string {
if a.parentAuth == nil {
return ""
}
return a.parentAuth.CdnUrl()
} }
// Check the interfaces are satisfied // Check the interfaces are satisfied

View File

@ -191,17 +191,15 @@ func parsePath(path string) (container, directory string, err error) {
func swiftConnection(name string) (*swift.Connection, error) { func swiftConnection(name string) (*swift.Connection, error) {
c := &swift.Connection{ c := &swift.Connection{
// Keep these in the same order as the Config for ease of checking // Keep these in the same order as the Config for ease of checking
UserName: fs.ConfigFileGet(name, "user"), UserName: fs.ConfigFileGet(name, "user"),
ApiKey: fs.ConfigFileGet(name, "key"), ApiKey: fs.ConfigFileGet(name, "key"),
AuthUrl: fs.ConfigFileGet(name, "auth"), AuthUrl: fs.ConfigFileGet(name, "auth"),
UserId: fs.ConfigFileGet(name, "user_id"), UserId: fs.ConfigFileGet(name, "user_id"),
Domain: fs.ConfigFileGet(name, "domain"), Domain: fs.ConfigFileGet(name, "domain"),
Tenant: fs.ConfigFileGet(name, "tenant"), Tenant: fs.ConfigFileGet(name, "tenant"),
TenantId: fs.ConfigFileGet(name, "tenant_id"), TenantId: fs.ConfigFileGet(name, "tenant_id"),
TenantDomain: fs.ConfigFileGet(name, "tenant_domain"), TenantDomain: fs.ConfigFileGet(name, "tenant_domain"),
Region: fs.ConfigFileGet(name, "region"), Region: fs.ConfigFileGet(name, "region"),
// I get the StorageUrl already here, in case the user wants to set it manually
// (e.g. when using alternate authentication)
StorageUrl: fs.ConfigFileGet(name, "storage_url"), StorageUrl: fs.ConfigFileGet(name, "storage_url"),
AuthToken: fs.ConfigFileGet(name, "auth_token"), AuthToken: fs.ConfigFileGet(name, "auth_token"),
AuthVersion: fs.ConfigFileGetInt(name, "auth_version", 0), AuthVersion: fs.ConfigFileGetInt(name, "auth_version", 0),
@ -231,6 +229,11 @@ func swiftConnection(name string) (*swift.Connection, error) {
return nil, err return nil, err
} }
} }
// Make sure we re-auth with the AuthToken and StorageUrl
// provided by wrapping the existing auth
if c.StorageUrl != "" || c.AuthToken != "" {
c.Auth = newAuth(c.Auth, c.StorageUrl, c.AuthToken)
}
return c, nil return c, nil
} }
@ -257,12 +260,6 @@ func NewFsWithConnection(name, root string, c *swift.Connection, noCheckContaine
WriteMimeType: true, WriteMimeType: true,
BucketBased: true, BucketBased: true,
}).Fill(f) }).Fill(f)
// StorageURL overloading
storageURL := fs.ConfigFileGet(name, "storage_url")
if storageURL != "" {
f.c.StorageUrl = storageURL
f.c.Auth = newAuth(f.c.Auth, storageURL)
}
if f.root != "" { if f.root != "" {
f.root += "/" f.root += "/"
// Check to see if the object exists - ignoring directory markers // Check to see if the object exists - ignoring directory markers