diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 5b3bab4..21f6934 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,11 @@ +# 0.1.2 + +- Support for disabling SSL verification of remote S3 certificates (default false) with the s3-disable-ssl-verify option in the configuration file. + # 0.1.1 - Added seek & length parameters to file download requests # 0.1.0 -- Initial release \ No newline at end of file +- Initial release diff --git a/app/blobstore.go b/app/blobstore.go index 8a5b38e..6575ce2 100644 --- a/app/blobstore.go +++ b/app/blobstore.go @@ -19,10 +19,11 @@ import ( const ( name = "blobstore" - version = "0.1.1" + version = "0.1.2" shockname = "Shock" shockver = "0.9.6" // do not increment deprecation = "The id and version fields are deprecated." + httpTimeout = 24 * time.Hour ) // expect initialization via go build -ldflags "-X main.gitCommit=$GIT_COMMIT" @@ -53,6 +54,7 @@ func main() { ServerVersionCompat: shockver, DeprecationWarning: deprecation, GitCommit: gitCommit, + HTTPTimeout: httpTimeout, }, ) if err != nil { @@ -62,8 +64,8 @@ func main() { server := &http.Server{ Addr: cfg.Host, Handler: serv, - ReadTimeout: 24 * time.Hour, - WriteTimeout: 24 * time.Hour, + ReadTimeout: httpTimeout, + WriteTimeout: httpTimeout, } // TODO BUGNASTY figure out how to abort when no more data is being sent https://groups.google.com/forum/#!topic/golang-nuts/Hmjf5Ws8g5w diff --git a/config/config_test.go b/config/config_test.go index dcbdbff..032143d 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -90,6 +90,7 @@ func (t *TestSuite) TestMinimalConfig() { S3AccessSecret: "sooporsekrit", S3Region: "us-west-1", S3DisableSSL: false, + S3DisableSSLVerify: false, AuthURL: u, AuthAdminRoles: &[]string{}, DontTrustXIPHeaders: false, @@ -109,6 +110,7 @@ func (t *TestSuite) TestMinimalConfigWhitespaceFields() { "s3-access-key = akey", "s3-access-secret = sooporsekrit", "s3-disable-ssl = \t tru ", + "s3-disable-ssl-verify = \t tru ", "s3-region = us-west-1 \t ", "kbase-auth-url = https://kbase.us/authyauth", "kbase-auth-admin-roles = \t ", @@ -127,6 +129,7 @@ func (t *TestSuite) TestMinimalConfigWhitespaceFields() { S3AccessSecret: "sooporsekrit", S3Region: "us-west-1", S3DisableSSL: false, + S3DisableSSLVerify: false, AuthURL: u, AuthAdminRoles: &[]string{}, DontTrustXIPHeaders: false, @@ -147,6 +150,7 @@ func (t *TestSuite) TestMaximalConfig() { "s3-access-secret = sooporsekrit", "s3-region = us-west-1", "s3-disable-ssl= true ", + "s3-disable-ssl-verify= true ", "kbase-auth-url = https://kbase.us/authyauth", "kbase-auth-admin-roles = \t , foo , \tbar\t , , baz ,,", "dont-trust-x-ip-headers = true \t ", @@ -165,6 +169,7 @@ func (t *TestSuite) TestMaximalConfig() { S3AccessKey: "akey", S3AccessSecret: "sooporsekrit", S3DisableSSL: true, + S3DisableSSLVerify: true, S3Region: "us-west-1", AuthURL: u, AuthAdminRoles: &[]string{"foo", "bar", "baz"}, diff --git a/deploy.cfg.example b/deploy.cfg.example index 5a6aeea..04af651 100644 --- a/deploy.cfg.example +++ b/deploy.cfg.example @@ -11,7 +11,7 @@ mongodb-database = blobstore #mongodb-user = [username] #mongodb-pwd = [password] -# S3 API parameters. All are required other than disable-ssl. +# S3 API parameters. All are required other than s3-disable-ssl and s3-disable-ssl-verify. # disable-ssl treats any value other than 'true' as false. s3-host = localhost:9000 # The bucket name must obey https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html @@ -20,7 +20,7 @@ s3-bucket = blobstore s3-access-key = [access key goes here] s3-access-secret = [access secret goes here] s3-region = us-west-1 -# Use plaintext to talk to destination S3. Default false. (false is not tested) +# Use plaintext to talk to destination S3. Default false. #s3-disable-ssl = false # Disable verifying the destination S3 SSL cert (e.g. for self-signed certs). Default false. #s3-disable-ssl-verify = false diff --git a/filestore/s3.go b/filestore/s3.go index 4592e10..4cad268 100644 --- a/filestore/s3.go +++ b/filestore/s3.go @@ -6,7 +6,6 @@ import ( "io" "net/http" "net/url" - "crypto/tls" "strconv" "strings" "time" @@ -34,19 +33,22 @@ type S3FileStore struct { s3client *s3.S3 minioClient *minio.Client bucket string - disableSSLverify bool + httpClient *http.Client } // NewS3FileStore creates a new S3 based file store. Files will be stored in the provided // bucket, which will be created if it doesn't exist. The provided clients must have write // privileges for the bucket. -// Two clients are currently required because they are better at different operations. +// Three clients are currently required because they are better at different operations: +// s3client: an aws-sdk s3 client +// minioClient: a minio-go client +// httpClient: an http.Client client (used directly for faster PUTs) // This may change in a future version if one client provides all the necessary operations. func NewS3FileStore( s3client *s3.S3, minioClient *minio.Client, bucket string, - disableSSLverify bool, + httpClient *http.Client, ) (*S3FileStore, error) { if s3client == nil { @@ -55,6 +57,9 @@ func NewS3FileStore( if minioClient == nil { return nil, errors.New("minioClient cannot be nil") } + if httpClient == nil { + return nil, errors.New("httpClient cannot be nil") + } bucket, err := checkBucketName(bucket) if err != nil { return nil, err @@ -65,7 +70,7 @@ func NewS3FileStore( // Ignore for now. return nil, err } - return &S3FileStore{s3client: s3client, minioClient: minioClient, bucket: bucket, disableSSLverify: disableSSLverify}, nil + return &S3FileStore{s3client: s3client, minioClient: minioClient, bucket: bucket, httpClient: httpClient}, nil } func checkBucketName(bucket string) (string, error) { @@ -132,16 +137,7 @@ func (fs *S3FileStore) StoreFile(le *logrus.Entry, p *StoreFileParams) (out *Fil req.Header.Set("x-amz-meta-Filename", p.filename) req.Header.Set("x-amz-meta-Format", p.format) - // disable SSL verify if necessary - customTransport := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: fs.disableSSLverify}, - } -// Timeout: time.Second * 10, - httpClient := &http.Client{ - Transport: customTransport, - } - - resp, err := httpClient.Do(req) + resp, err := fs.httpClient.Do(req) if err != nil { // don't expose the presigned url in the returned error errstr := err.(*url.Error).Err.Error() diff --git a/filestore/s3_test.go b/filestore/s3_test.go index abbb3a5..5930f71 100644 --- a/filestore/s3_test.go +++ b/filestore/s3_test.go @@ -9,6 +9,8 @@ import ( "strings" "testing" "time" + "net/http" + "crypto/tls" "github.com/kbase/blobstore/core/values" "github.com/sirupsen/logrus" @@ -30,6 +32,17 @@ type TestSuite struct { deleteTempDir bool } +func httpClient(insecureSkipVerify bool) *http.Client { + + customTransport := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: insecureSkipVerify}, + } + customHTTPClient := &http.Client{ + Transport: customTransport, + Timeout: 24 * time.Hour } + return customHTTPClient +} + func (t *TestSuite) SetupSuite() { tcfg, err := testhelpers.GetConfig() if err != nil { @@ -49,6 +62,7 @@ func (t *TestSuite) SetupSuite() { t.minio = minio t.deleteTempDir = tcfg.DeleteTempDir t.loggerhook = logrust.NewGlobal() + logrus.SetOutput(ioutil.Discard) } @@ -82,8 +96,9 @@ func (t *TestSuite) TestConstructWithGoodBucketNames() { } ls := b.String() t.Equal(63, len(ls), "incorrect string length") + httpClient := httpClient(false) for _, bucket := range []string{"foo", ls} { - fstore, err := NewS3FileStore(cli, min, bucket, false) + fstore, err := NewS3FileStore(cli, min, bucket, httpClient) t.NotNil(fstore, "expected filestore client") t.Nil(err, "unexpected error") } @@ -92,13 +107,16 @@ func (t *TestSuite) TestConstructWithGoodBucketNames() { func (t *TestSuite) TestConstructFail() { min, _ := t.minio.CreateMinioClient() cli := t.minio.CreateS3Client() - constructFail(t, nil, min, "s", errors.New("s3client cannot be nil")) - constructFail(t, cli, nil, "s", errors.New("minioClient cannot be nil")) + httpClient := httpClient(false) + constructFail(t, nil, min, httpClient, "s", errors.New("s3client cannot be nil")) + constructFail(t, cli, nil, httpClient, "s", errors.New("minioClient cannot be nil")) + constructFail(t, cli, min, nil, "s", errors.New("httpClient cannot be nil")) } func (t *TestSuite) TestConstructFailBadBucketName() { min, _ := t.minio.CreateMinioClient() cli := t.minio.CreateS3Client() + httpClient := httpClient(false) b := strings.Builder{} for i := 0; i < 6; i++ { @@ -118,12 +136,12 @@ func (t *TestSuite) TestConstructFailBadBucketName() { } for bucket, er := range testcases { - constructFail(t, cli, min, bucket, errors.New(er)) + constructFail(t, cli, min, httpClient, bucket, errors.New(er)) } } -func constructFail(t *TestSuite, client *s3.S3, min *minio.Client, bucket string, expected error) { - fstore, err := NewS3FileStore(client, min, bucket, false) +func constructFail(t *TestSuite, client *s3.S3, min *minio.Client, httpClient *http.Client, bucket string, expected error) { + fstore, err := NewS3FileStore(client, min, bucket, httpClient) if err == nil { t.FailNow("expected error") } @@ -136,13 +154,14 @@ func constructFail(t *TestSuite, client *s3.S3, min *minio.Client, bucket string func (t *TestSuite) TestConstructWithExistingBucket() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() + httpClient := httpClient(false) bucket := "somebucket" input := &s3.CreateBucketInput{Bucket: aws.String(bucket)} _, err := s3client.CreateBucket(input) if err != nil { t.FailNow(err.Error()) } - fstore, err := NewS3FileStore(s3client, mclient, bucket, false) + fstore, err := NewS3FileStore(s3client, mclient, bucket, httpClient) if err != nil { t.FailNow(err.Error()) } @@ -153,34 +172,39 @@ func (t *TestSuite) TestConstructWithExistingBucket() { } func (t *TestSuite) TestStoreAndGet() { - t.storeAndGet("", "", 0, 0, "012345678910") + t.storeAndGet("", "", 0, 0, false, "012345678910") } + +func (t *TestSuite) TestStoreAndGetInsecureVerify() { + t.storeAndGet("", "", 0, 0, true, "012345678910") +} + func (t *TestSuite) TestStoreAndGetWithMeta() { - t.storeAndGet("fn", "json", 0, 0, "012345678910") + t.storeAndGet("fn", "json", 0, 0, false, "012345678910") } func (t *TestSuite) TestStoreAndGetWithSeek() { - t.storeAndGet("", "", 3, 0, "345678910") + t.storeAndGet("", "", 3, 0, false, "345678910") } func (t *TestSuite) TestStoreAndGetWithExactSeek() { - t.storeAndGet("", "", 11, 0, "0") + t.storeAndGet("", "", 11, 0, false, "0") } func (t *TestSuite) TestStoreAndGetWithLength() { - t.storeAndGet("", "", 0, 8, "01234567") + t.storeAndGet("", "", 0, 8, false, "01234567") } func (t *TestSuite) TestStoreAndGetWithSeekAndLength() { - t.storeAndGet("", "", 1, 5, "12345") + t.storeAndGet("", "", 1, 5, false, "12345") } func (t *TestSuite) TestStoreAndGetWithSeekAndExactLength() { - t.storeAndGet("", "", 1, 11, "12345678910") + t.storeAndGet("", "", 1, 11, false, "12345678910") } func (t *TestSuite) TestStoreAndGetWithSeekAndExcessLength() { - t.storeAndGet("", "", 1, 15, "12345678910") + t.storeAndGet("", "", 1, 15, false, "12345678910") } func (t *TestSuite) storeAndGet( @@ -188,11 +212,13 @@ func (t *TestSuite) storeAndGet( format string, seek uint64, length uint64, + insecureSkipVerify bool, expectedfile string, ) { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(insecureSkipVerify) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) p, _ := NewStoreFileParams( "myid", 12, @@ -241,7 +267,8 @@ func (t *TestSuite) storeAndGet( func (t *TestSuite) TestStoreWithNilInput() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) res, err := fstore.StoreFile(nil, &StoreFileParams{}) // DO NOT init SFP like this t.Nil(res, "expected error") @@ -256,7 +283,8 @@ func (t *TestSuite) TestStoreWithNilInput() { func (t *TestSuite) TestStoreWithIncorrectSize() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) p, _ := NewStoreFileParams( "myid", 11, @@ -278,7 +306,8 @@ func (t *TestSuite) TestStoreWithIncorrectSize() { func (t *TestSuite) TestStoreFailNoBucket() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) t.minio.Clear(false) @@ -308,7 +337,8 @@ func (t *TestSuite) TestStoreFailNoBucket() { func (t *TestSuite) TestGetWithBlankID() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) res, err := fstore.GetFile("", 0, 0) if res != nil { @@ -320,7 +350,8 @@ func (t *TestSuite) TestGetWithBlankID() { func (t *TestSuite) TestGetWithNonexistentID() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) p, _ := NewStoreFileParams( "myid", 12, @@ -344,7 +375,8 @@ func (t *TestSuite) assertNoFile(fstore FileStore, id string) { func (t *TestSuite) TestGetWithExcessSeek() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) p, _ := NewStoreFileParams( "myid", 12, @@ -372,7 +404,8 @@ func (t *TestSuite) TestGetWithoutMetaData() { id := "myid" s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, bkt, false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, bkt, httpClient) _, err := s3client.PutObject(&s3.PutObjectInput{ Bucket: &bkt, @@ -414,7 +447,8 @@ func (t *TestSuite) TestGetWithoutMetaData() { func (t *TestSuite) TestDeleteObject() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) p, _ := NewStoreFileParams( "myid", 12, @@ -434,7 +468,8 @@ func (t *TestSuite) TestDeleteObject() { func (t *TestSuite) TestDeleteObjectWrongID() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) p, _ := NewStoreFileParams( "myid", 12, @@ -460,7 +495,8 @@ func (t *TestSuite) TestDeleteObjectWrongID() { func (t *TestSuite) TestDeleteWithBlankID() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) err := fstore.DeleteFile("") t.Equal(errors.New("id cannot be empty or whitespace only"), err, "incorrect err") @@ -469,7 +505,8 @@ func (t *TestSuite) TestDeleteWithBlankID() { func (t *TestSuite) TestDeleteFailNoBucket() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) t.minio.Clear(false) @@ -493,7 +530,8 @@ func (t *TestSuite) copy( format string) { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) p, _ := NewStoreFileParams( srcobj, 12, @@ -544,7 +582,8 @@ func (t *TestSuite) copy( func (t *TestSuite) TestCopyBadInput() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) t.copyFail(fstore, " \t \n ", "bar", errors.New("sourceID cannot be empty or whitespace only")) @@ -566,7 +605,8 @@ func (t *TestSuite) copyFail(fstore FileStore, src string, dst string, expected func (t *TestSuite) TestCopyNonExistentFile() { s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) p, _ := NewStoreFileParams( "myid", 12, @@ -594,7 +634,8 @@ func (t *TestSuite) testCopyLargeObject() { } s3client := t.minio.CreateS3Client() mclient, _ := t.minio.CreateMinioClient() - fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", false) + httpClient := httpClient(false) + fstore, _ := NewS3FileStore(s3client, mclient, "mybucket", httpClient) p, _ := NewStoreFileParams("myid", fi.Size(), reader) start := time.Now() obj, err := fstore.StoreFile(logrus.WithField("a", "b"), p) diff --git a/service/build.go b/service/build.go index 22888b3..77bcec8 100644 --- a/service/build.go +++ b/service/build.go @@ -4,6 +4,7 @@ import ( "context" "net/http" "crypto/tls" + "time" "github.com/aws/aws-sdk-go/service/s3" @@ -37,7 +38,9 @@ type Dependencies struct { } // ConstructDependencies builds the blobstore dependencies from a configuration. -func constructDependencies(cfg *config.Config) (*Dependencies, error) { +// cfg is a configuration structure populated from the config file +// HTTPTimeout is a timeout for the various clients connecting to the S3 backend (s3, minio, http) +func constructDependencies(cfg *config.Config, HTTPTimeout time.Duration) (*Dependencies, error) { d := Dependencies{} auth, err := buildAuth(cfg) if err != nil { @@ -48,7 +51,7 @@ func constructDependencies(cfg *config.Config) (*Dependencies, error) { if err != nil { return nil, err } - fs, err := buildFileStore(cfg) + fs, err := buildFileStore(cfg, HTTPTimeout) if err != nil { return nil, err } @@ -56,18 +59,25 @@ func constructDependencies(cfg *config.Config) (*Dependencies, error) { return &d, nil } -func buildFileStore(cfg *config.Config) (filestore.FileStore, error) { +func buildFileStore(cfg *config.Config, HTTPTimeout time.Duration) (filestore.FileStore, error) { trueref := true sess := session.Must(session.NewSession()) creds := credentials.NewStaticCredentials(cfg.S3AccessKey, cfg.S3AccessSecret, "") // need a custom transport to support not verifying SSL cert + // if you modify the SSL code, be sure to manually test against + // a minio instance with a self-signed certificate customTransport := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: cfg.S3DisableSSLVerify}, + TLSClientConfig: &tls.Config{InsecureSkipVerify: cfg.S3DisableSSLVerify}, } - customHTTPClient := &http.Client{Transport: customTransport} + customHTTPClient := &http.Client{ + Transport: customTransport, + Timeout: HTTPTimeout } + // use our http.Client with the aws client + // this is encouraged, see https://docs.aws.amazon.com/sdk-for-go/api/aws/ + // (search for "SDK Default HTTP Client") awscli := s3.New(sess, &aws.Config{ Credentials: creds, Endpoint: &cfg.S3Host, @@ -78,12 +88,14 @@ func buildFileStore(cfg *config.Config) (filestore.FileStore, error) { minioClient, err := minio.NewWithRegion( cfg.S3Host, cfg.S3AccessKey, cfg.S3AccessSecret, !cfg.S3DisableSSL, cfg.S3Region) - minioClient.SetCustomTransport(customTransport) + // use our http.Transport with the minio client + // this is typical, see https://godoc.org/gopkg.in/minio/minio-go.v1#Client.SetCustomTransport + minioClient.SetCustomTransport(customTransport) if err != nil { return nil, err } - return filestore.NewS3FileStore(awscli, minioClient, cfg.S3Bucket, cfg.S3DisableSSLVerify) + return filestore.NewS3FileStore(awscli, minioClient, cfg.S3Bucket, customHTTPClient) } func buildNodeStore(cfg *config.Config) (nodestore.NodeStore, error) { diff --git a/service/server.go b/service/server.go index bfb4a2e..e331aef 100644 --- a/service/server.go +++ b/service/server.go @@ -55,6 +55,10 @@ type ServerStaticConf struct { DeprecationWarning string // GitCommit is the git commit from which the server was built. GitCommit string + // HTTPTimeout is the timeout of the blobstore http.Server, + // the minio http.Client, the AWS http.Client, + // and the custom http.Client that pushes to S3 + HTTPTimeout time.Duration } // Server the blobstore server @@ -73,7 +77,7 @@ func New(cfg *config.Config, sconf ServerStaticConf) (*Server, error) { if cfg.AuthURL.Scheme != "https" { logrus.Warnf("Insecure auth url " + cfg.AuthURL.String()) } - deps, err := constructDependencies(cfg) + deps, err := constructDependencies(cfg, sconf.HTTPTimeout) if err != nil { return nil, err // this is a pain to test }