diff --git a/app/diagnostics.go b/app/diagnostics.go
index f12681d01a..983ce8077d 100644
--- a/app/diagnostics.go
+++ b/app/diagnostics.go
@@ -275,6 +275,7 @@ func trackConfig() {
"enable_public_links": utils.Cfg.FileSettings.EnablePublicLink,
"driver_name": utils.Cfg.FileSettings.DriverName,
"amazon_s3_ssl": *utils.Cfg.FileSettings.AmazonS3SSL,
+ "amazon_s3_sse": *utils.Cfg.FileSettings.AmazonS3SSE,
"amazon_s3_signv2": *utils.Cfg.FileSettings.AmazonS3SignV2,
"max_file_size": *utils.Cfg.FileSettings.MaxFileSize,
"enable_file_attachments": *utils.Cfg.FileSettings.EnableFileAttachments,
diff --git a/app/file.go b/app/file.go
index 74f70ec167..03d898acd7 100644
--- a/app/file.go
+++ b/app/file.go
@@ -115,6 +115,7 @@ func MoveFile(oldPath, newPath string) *model.AppError {
secretKey := utils.Cfg.FileSettings.AmazonS3SecretAccessKey
secure := *utils.Cfg.FileSettings.AmazonS3SSL
signV2 := *utils.Cfg.FileSettings.AmazonS3SignV2
+ encrypt := *utils.Cfg.FileSettings.AmazonS3SSE
region := utils.Cfg.FileSettings.AmazonS3Region
s3Clnt, err := s3New(endpoint, accessKey, secretKey, secure, signV2, region)
if err != nil {
@@ -123,7 +124,7 @@ func MoveFile(oldPath, newPath string) *model.AppError {
bucket := utils.Cfg.FileSettings.AmazonS3Bucket
source := s3.NewSourceInfo(bucket, oldPath, nil)
- destination, err := s3.NewDestinationInfo(bucket, newPath, nil, nil)
+ destination, err := s3.NewDestinationInfo(bucket, newPath, nil, CopyMetadata(encrypt))
if err != nil {
return model.NewLocAppError("moveFile", "api.file.write_file.s3.app_error", nil, err.Error())
}
@@ -155,6 +156,7 @@ func WriteFile(f []byte, path string) *model.AppError {
secretKey := utils.Cfg.FileSettings.AmazonS3SecretAccessKey
secure := *utils.Cfg.FileSettings.AmazonS3SSL
signV2 := *utils.Cfg.FileSettings.AmazonS3SignV2
+ encrypt := *utils.Cfg.FileSettings.AmazonS3SSE
region := utils.Cfg.FileSettings.AmazonS3Region
s3Clnt, err := s3New(endpoint, accessKey, secretKey, secure, signV2, region)
if err != nil {
@@ -163,12 +165,12 @@ func WriteFile(f []byte, path string) *model.AppError {
bucket := utils.Cfg.FileSettings.AmazonS3Bucket
ext := filepath.Ext(path)
-
+ metaData := S3Metadata(encrypt, "binary/octet-stream")
if model.IsFileExtImage(ext) {
- _, err = s3Clnt.PutObject(bucket, path, bytes.NewReader(f), model.GetImageMimeType(ext))
- } else {
- _, err = s3Clnt.PutObject(bucket, path, bytes.NewReader(f), "binary/octet-stream")
+ metaData = S3Metadata(encrypt, model.GetImageMimeType(ext))
}
+
+ _, err = s3Clnt.PutObjectWithMetadata(bucket, path, bytes.NewReader(f), metaData, nil)
if err != nil {
return model.NewLocAppError("WriteFile", "api.file.write_file.s3.app_error", nil, err.Error())
}
@@ -633,3 +635,20 @@ func GetFileInfo(fileId string) (*model.FileInfo, *model.AppError) {
return result.Data.(*model.FileInfo), nil
}
}
+
+func S3Metadata(encrypt bool, contentType string) map[string][]string {
+ metaData := make(map[string][]string)
+ if contentType != "" {
+ metaData["Content-Type"] = []string{"contentType"}
+ }
+ if encrypt {
+ metaData["x-amz-server-side-encryption"] = []string{"AES256"}
+ }
+ return metaData
+}
+
+func CopyMetadata(encrypt bool) map[string]string {
+ metaData := make(map[string]string)
+ metaData["x-amz-server-side-encryption"] = "AES256"
+ return metaData
+}
diff --git a/model/config.go b/model/config.go
index 55fe8490be..1717d61a08 100644
--- a/model/config.go
+++ b/model/config.go
@@ -262,6 +262,7 @@ type FileSettings struct {
AmazonS3Endpoint string
AmazonS3SSL *bool
AmazonS3SignV2 *bool
+ AmazonS3SSE *bool
}
type EmailSettings struct {
@@ -551,6 +552,11 @@ func (o *Config) SetDefaults() {
// Signature v2 is not enabled by default.
}
+ if o.FileSettings.AmazonS3SSE == nil {
+ o.FileSettings.AmazonS3SSE = new(bool)
+ *o.FileSettings.AmazonS3SSE = false // Not Encrypted by default.
+ }
+
if o.FileSettings.EnableFileAttachments == nil {
o.FileSettings.EnableFileAttachments = new(bool)
*o.FileSettings.EnableFileAttachments = true
diff --git a/model/config_test.go b/model/config_test.go
index 1a944710fe..f10e2d0cdc 100644
--- a/model/config_test.go
+++ b/model/config_test.go
@@ -24,3 +24,12 @@ func TestConfigDefaultEmailNotificationContentsType(t *testing.T) {
t.Fatal("EmailSettings.EmailNotificationContentsType should default to 'full'")
}
}
+
+func TestConfigDefaultFileSettingsS3SSE(t *testing.T) {
+ c1 := Config{}
+ c1.SetDefaults()
+
+ if *c1.FileSettings.AmazonS3SSE != false {
+ t.Fatal("FileSettings.AmazonS3SSE should default to false")
+ }
+}
diff --git a/webapp/components/admin_console/storage_settings.jsx b/webapp/components/admin_console/storage_settings.jsx
index 4e0d9d19b7..89a56c04bf 100644
--- a/webapp/components/admin_console/storage_settings.jsx
+++ b/webapp/components/admin_console/storage_settings.jsx
@@ -36,6 +36,7 @@ export default class StorageSettings extends AdminSettings {
config.FileSettings.AmazonS3Bucket = this.state.amazonS3Bucket;
config.FileSettings.AmazonS3Endpoint = this.state.amazonS3Endpoint;
config.FileSettings.AmazonS3SSL = this.state.amazonS3SSL;
+ config.FileSettings.AmazonS3SSE = this.state.amazonS3SSE;
return config;
}
@@ -52,7 +53,8 @@ export default class StorageSettings extends AdminSettings {
amazonS3SecretAccessKey: config.FileSettings.AmazonS3SecretAccessKey,
amazonS3Bucket: config.FileSettings.AmazonS3Bucket,
amazonS3Endpoint: config.FileSettings.AmazonS3Endpoint,
- amazonS3SSL: config.FileSettings.AmazonS3SSL
+ amazonS3SSL: config.FileSettings.AmazonS3SSL,
+ amazonS3SSE: config.FileSettings.AmazonS3SSE
};
}
@@ -252,6 +254,25 @@ export default class StorageSettings extends AdminSettings {
onChange={this.handleChange}
disabled={this.state.driverName !== DRIVER_S3}
/>
+
+ }
+ placeholder={Utils.localizeMessage('admin.image.AmazonSSEExample', 'Ex "false"')}
+ helpText={
+
+ }
+ value={this.state.AmazonSSE}
+ onChange={this.handleChange}
+ disabled={this.state.driverName !== DRIVER_S3}
+ />
documentation to learn more.",
+ "admin.image.amazonS3SSEExample": "E.g.: \"false\"",
+ "admin.image.amazonS3SSETitle": "Enable Server-Side Encryption for Amazon S3:",
"admin.image.amazonS3SecretDescription": "Obtain this credential from your Amazon EC2 administrator.",
"admin.image.amazonS3SecretExample": "E.g.: \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"",
"admin.image.amazonS3SecretTitle": "Amazon S3 Secret Access Key:",