-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support swift tempURLs #37
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package client | ||
|
||
import ( | ||
"github.com/cloudfoundry/bosh-s3cli/config" | ||
"time" | ||
) | ||
|
||
type SignURLProvider interface { | ||
Sign(action string, objectID string, expiration time.Duration) (string, error) | ||
} | ||
|
||
func NewSignURLProvider(s3BlobstoreClient S3Blobstore, s3cliConfig *config.S3Cli) (SignURLProvider, error) { | ||
if s3cliConfig.SwiftAuthAccount != "" { | ||
client := NewSwiftClient(s3cliConfig) | ||
return &client, nil | ||
} else { | ||
return &s3BlobstoreClient, nil | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package client | ||
|
||
import ( | ||
"crypto/hmac" | ||
"crypto/sha256" | ||
"encoding/hex" | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"github.com/cloudfoundry/bosh-s3cli/config" | ||
) | ||
|
||
type SwiftBlobstore struct { | ||
s3cliConfig *config.S3Cli | ||
} | ||
|
||
func NewSwiftClient(s3cliConfig *config.S3Cli) SwiftBlobstore { | ||
return SwiftBlobstore{s3cliConfig: s3cliConfig} | ||
} | ||
|
||
func (client *SwiftBlobstore) Sign(objectID string, action string, expiration time.Duration) (string, error) { | ||
action = strings.ToUpper(action) | ||
switch action { | ||
case "GET", "PUT": | ||
return client.SignedURL(action, objectID, expiration) | ||
default: | ||
return "", fmt.Errorf("action not implemented: %s", action) | ||
} | ||
} | ||
|
||
func (client *SwiftBlobstore) SignedURL(action string, objectID string, expiration time.Duration) (string, error) { | ||
path := fmt.Sprintf("/v1/%s/%s/%s", client.s3cliConfig.SwiftAuthAccount, client.s3cliConfig.BucketName, objectID) | ||
|
||
expires := time.Now().Add(expiration).Unix() | ||
hmacBody := action + "\n" + strconv.FormatInt(expires, 10) + "\n" + path | ||
|
||
h := hmac.New(sha256.New, []byte(client.s3cliConfig.SwiftTempURLKey)) | ||
h.Write([]byte(hmacBody)) | ||
signature := hex.EncodeToString(h.Sum(nil)) | ||
|
||
url := fmt.Sprintf("https://%s%s?temp_url_sig=%s&temp_url_expires=%d", client.s3cliConfig.Host, path, signature, expires) | ||
|
||
return url, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,11 @@ func main() { | |
log.Fatalln(err) | ||
} | ||
|
||
signURLProvider, err := client.NewSignURLProvider(blobstoreClient, &s3Config) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
||
nonFlagArgs := flag.Args() | ||
if len(nonFlagArgs) < 2 { | ||
log.Fatalf("Expected at least two arguments got %d\n", len(nonFlagArgs)) | ||
|
@@ -114,7 +119,7 @@ func main() { | |
log.Fatalf("Expiration should be in the format of a duration i.e. 1h, 60m, 3600s. Got: %s", nonFlagArgs[3]) | ||
} | ||
|
||
signedURL, err := blobstoreClient.Sign(objectID, action, expiration) | ||
signedURL, err := signURLProvider.Sign(objectID, action, expiration) | ||
Comment on lines
-117
to
+122
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious why there is a conditional in What I have in mind would look something like: func (client *S3Blobstore) Sign(objectID string, action string, expiration time.Duration) (string, error) {
if client.s3cliConfig.SwiftAuthAccount != "" {
return client.swiftSign(objectID, action, expiration)
}
return client.s3Sign(objectID, action, expiration)
}
func (client *S3Blobstore) s3Sign(objectID string, action string, expiration time.Duration) (string, error) {
// implementation
}
func (client *S3Blobstore) swiftSign(objectID string, action string, expiration time.Duration) (string, error) {
// implementation
} Something like this would add swift signing behavior without adding a different signing-only client, and hides the details behind There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would not mix up the S3 client code with Swift specific implementations because I wouldn't expect Swift Code in that client. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess I was confused about the origin of I agree that the Swift code doesn't belong on the I do think that func (c *GenericS3Blobstore) Sign(objectID string, action string, expiration time.Duration) (string, error) {
if client.s3cliConfig.SwiftAuthAccount != "" {
return c.someEntityWhichSupportsSwift.Sign(objectID, action, expiration)
}
return c.someEntityWhichSupportsAwsS3.Sign(objectID, action, expiration)
} The type Blobstore interface {
Put(src io.ReadSeeker, dest string) error
Delete(dest string) error
Exists(dest string) (bool, error)
Sign(objectID string, action string, expiration time.Duration) (string, error)
} The code in |
||
|
||
if err != nil { | ||
log.Fatalf("Failed to sign request: %s", err) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method should be private