MM-29572: Add Bifrost support to codebase (#15955)
* MM-29572: Add Bifrost support to codebase We use a custom transport for minio when an environment variable indicates that Mattermost is running in cloud. The transport is used to redirect the request to the S3 endpoint set in the config. And the scheme is set depending on if S3SSL is set. A custom credentials provider is needed to return empty credentials which will be overridden by the service anyways. This is just to allow the minio client library to work transparently without knowing that there is something else in the middle intercepting requests. https://mattermost.atlassian.net/browse/MM-29572 * incorporate review comments * Update services/filesstore/s3_overrides.go Co-authored-by: Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com> * Change to new env key Co-authored-by: Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
b5047e51fe
Коммит
4b57cea789
56
services/filesstore/s3_overrides.go
Обычный файл
56
services/filesstore/s3_overrides.go
Обычный файл
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package filesstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
)
|
||||
|
||||
// customTransport is used to point the request to a different server.
|
||||
// This is helpful in situations where a different service is handling AWS S3 requests
|
||||
// from multiple Mattermost applications, and the Mattermost service itself does not
|
||||
// have any S3 credentials.
|
||||
type customTransport struct {
|
||||
base http.RoundTripper
|
||||
host string
|
||||
scheme string
|
||||
client http.Client
|
||||
}
|
||||
|
||||
// RoundTrip implements the http.Roundtripper interface.
|
||||
func (t *customTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
// Rountrippers should not modify the original request.
|
||||
newReq := req.Clone(context.Background())
|
||||
*newReq.URL = *req.URL
|
||||
req.URL.Scheme = t.scheme
|
||||
req.URL.Host = t.host
|
||||
return t.client.Do(req)
|
||||
}
|
||||
|
||||
// customProvider is a dummy credentials provider for the minio client to work
|
||||
// without actually providing credentials. This is needed with a custom transport
|
||||
// in cases where the minio client does not actually have credentials with itself,
|
||||
// rather needs responses from another entity.
|
||||
//
|
||||
// It satisfies the credentials.Provider interface.
|
||||
type customProvider struct {
|
||||
isSignV2 bool
|
||||
}
|
||||
|
||||
// Retrieve just returns empty credentials.
|
||||
func (cp customProvider) Retrieve() (credentials.Value, error) {
|
||||
sign := credentials.SignatureV4
|
||||
if cp.isSignV2 {
|
||||
sign = credentials.SignatureV2
|
||||
}
|
||||
return credentials.Value{
|
||||
SignerType: sign,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// IsExpired always returns false.
|
||||
func (cp customProvider) IsExpired() bool { return false }
|
||||
@@ -72,7 +72,10 @@ func NewS3FileBackend(settings *model.FileSettings, enableComplianceFeatures boo
|
||||
func (b *S3FileBackend) s3New() (*s3.Client, error) {
|
||||
var creds *credentials.Credentials
|
||||
|
||||
if b.accessKey == "" && b.secretKey == "" {
|
||||
isCloud := os.Getenv("MM_CLOUD_FILESTORE_BIFROST") != ""
|
||||
if isCloud {
|
||||
creds = credentials.New(customProvider{isSignV2: b.signV2})
|
||||
} else if b.accessKey == "" && b.secretKey == "" {
|
||||
creds = credentials.NewIAM("")
|
||||
} else if b.signV2 {
|
||||
creds = credentials.NewStatic(b.accessKey, b.secretKey, "", credentials.SignatureV2)
|
||||
@@ -85,6 +88,24 @@ func (b *S3FileBackend) s3New() (*s3.Client, error) {
|
||||
Secure: b.secure,
|
||||
Region: b.region,
|
||||
}
|
||||
|
||||
// If this is a cloud installation, we override the default transport.
|
||||
if isCloud {
|
||||
tr, err := s3.DefaultTransport(b.secure)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scheme := "http"
|
||||
if b.secure {
|
||||
scheme = "https"
|
||||
}
|
||||
opts.Transport = &customTransport{
|
||||
base: tr,
|
||||
host: b.endpoint,
|
||||
scheme: scheme,
|
||||
}
|
||||
}
|
||||
|
||||
s3Clnt, err := s3.New(b.endpoint, &opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Ссылка в новой задаче
Block a user