From 3f6bd0606aa69b3fa6ddacc2559292d9b6473618 Mon Sep 17 00:00:00 2001 From: Gary Windham Date: Sat, 5 Jul 2014 12:33:39 -0700 Subject: [PATCH 1/2] support for EC2 IAM roles with Amazon S3 file store/backup --- app/models/admin_dashboard_data.rb | 4 ++-- app/models/backup.rb | 16 +++++++++++----- config/locales/server.en.yml | 1 + config/site_settings.yml | 1 + lib/file_store/s3_store.rb | 14 ++++++++++---- 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/app/models/admin_dashboard_data.rb b/app/models/admin_dashboard_data.rb index e6dbd86966f..90fc388056f 100644 --- a/app/models/admin_dashboard_data.rb +++ b/app/models/admin_dashboard_data.rb @@ -135,8 +135,8 @@ class AdminDashboardData end def s3_config_check - return I18n.t('dashboard.s3_config_warning') if SiteSetting.enable_s3_uploads and (SiteSetting.s3_access_key_id.blank? or SiteSetting.s3_secret_access_key.blank? or SiteSetting.s3_upload_bucket.blank?) - return I18n.t('dashboard.s3_backup_config_warning') if SiteSetting.enable_s3_backups and (SiteSetting.s3_access_key_id.blank? or SiteSetting.s3_secret_access_key.blank? or SiteSetting.s3_backup_bucket.blank?) + return I18n.t('dashboard.s3_config_warning') if SiteSetting.enable_s3_uploads and ((!SiteSetting.s3_use_iam_profile and (SiteSetting.s3_access_key_id.blank? or SiteSetting.s3_secret_access_key.blank?)) or SiteSetting.s3_upload_bucket.blank?) + return I18n.t('dashboard.s3_backup_config_warning') if SiteSetting.enable_s3_backups and ((!SiteSetting.s3_use_iam_profile and (SiteSetting.s3_access_key_id.blank? or SiteSetting.s3_secret_access_key.blank?)) or SiteSetting.s3_backup_bucket.blank?) nil end diff --git a/app/models/backup.rb b/app/models/backup.rb index 1cd40fdb162..14b1e48d4eb 100644 --- a/app/models/backup.rb +++ b/app/models/backup.rb @@ -73,18 +73,24 @@ class Backup private def s3_options - { + options = { provider: 'AWS', - aws_access_key_id: SiteSetting.s3_access_key_id, - aws_secret_access_key: SiteSetting.s3_secret_access_key, region: SiteSetting.s3_region.blank? ? "us-east-1" : SiteSetting.s3_region, } + if (SiteSetting.s3_use_iam_profile.present?) + options.merge!(:use_iam_profile => true) + else + options.merge!(:aws_access_key_id => SiteSetting.s3_access_key_id, + :aws_secret_access_key => SiteSetting.s3_secret_access_key) + end + options end def fog return @fog if @fog - return unless SiteSetting.s3_access_key_id.present? && - SiteSetting.s3_secret_access_key.present? && + return unless ((SiteSetting.s3_access_key_id.present? && + SiteSetting.s3_secret_access_key.present?) || + SiteSetting.s3_use_iam_profile.present?) && SiteSetting.s3_backup_bucket.present? require 'fog' @fog = Fog::Storage.new(s3_options) diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 1a1e3d84e4a..5f3769efe50 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -810,6 +810,7 @@ en: clean_orphan_uploads_grace_period_hours: "Grace period (in hours) before an orphan upload is removed." purge_deleted_uploads_grace_period_days: "Grace period (in days) before a deleted upload is erased." enable_s3_uploads: "Place uploads on Amazon S3 storage." + s3_use_iam_profile: 'Use AWS EC2 IAM role to retrieve keys. NOTE: enabling will override "s3 access key id" and "s3 secret access key" settings.' s3_upload_bucket: "The Amazon S3 bucket name that files will be uploaded into. WARNING: must be lowercase, no periods." s3_access_key_id: "The Amazon S3 access key id that will be used to upload images." s3_secret_access_key: "The Amazon S3 secret access key that will be used to upload images." diff --git a/config/site_settings.yml b/config/site_settings.yml index 93275554540..23ed198d953 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -422,6 +422,7 @@ files: clean_orphan_uploads_grace_period_hours: 1 purge_deleted_uploads_grace_period_days: 30 enable_s3_uploads: false + s3_use_iam_profile: false s3_access_key_id: '' s3_secret_access_key: '' s3_region: diff --git a/lib/file_store/s3_store.rb b/lib/file_store/s3_store.rb index a74b5e724ef..7510963a8b3 100644 --- a/lib/file_store/s3_store.rb +++ b/lib/file_store/s3_store.rb @@ -98,20 +98,26 @@ module FileStore def check_missing_site_settings raise Discourse::SiteSettingMissing.new("s3_upload_bucket") if SiteSetting.s3_upload_bucket.blank? - raise Discourse::SiteSettingMissing.new("s3_access_key_id") if SiteSetting.s3_access_key_id.blank? - raise Discourse::SiteSettingMissing.new("s3_secret_access_key") if SiteSetting.s3_secret_access_key.blank? + unless SiteSetting.s3_use_iam_profile.present? + raise Discourse::SiteSettingMissing.new("s3_access_key_id") if SiteSetting.s3_access_key_id.blank? + raise Discourse::SiteSettingMissing.new("s3_secret_access_key") if SiteSetting.s3_secret_access_key.blank? + end end def s3_options options = { provider: 'AWS', - aws_access_key_id: SiteSetting.s3_access_key_id, - aws_secret_access_key: SiteSetting.s3_secret_access_key, scheme: SiteSetting.scheme, # cf. https://github.com/fog/fog/issues/2381 path_style: dns_compatible?(s3_bucket, SiteSetting.use_https?), } options[:region] = SiteSetting.s3_region unless SiteSetting.s3_region.empty? + if (SiteSetting.s3_use_iam_profile.present?) + options.merge!(:use_iam_profile => true) + else + options.merge!(:aws_access_key_id => SiteSetting.s3_access_key_id, + :aws_secret_access_key => SiteSetting.s3_secret_access_key) + end options end From a28d38d1ed1a29cfa7e20425dcfbe5cea87af3f2 Mon Sep 17 00:00:00 2001 From: Gary Windham Date: Sat, 5 Jul 2014 15:16:13 -0700 Subject: [PATCH 2/2] refactor multiple instances of S3 key check logic to single variable --- app/models/admin_dashboard_data.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/models/admin_dashboard_data.rb b/app/models/admin_dashboard_data.rb index 90fc388056f..9444677c50e 100644 --- a/app/models/admin_dashboard_data.rb +++ b/app/models/admin_dashboard_data.rb @@ -135,8 +135,10 @@ class AdminDashboardData end def s3_config_check - return I18n.t('dashboard.s3_config_warning') if SiteSetting.enable_s3_uploads and ((!SiteSetting.s3_use_iam_profile and (SiteSetting.s3_access_key_id.blank? or SiteSetting.s3_secret_access_key.blank?)) or SiteSetting.s3_upload_bucket.blank?) - return I18n.t('dashboard.s3_backup_config_warning') if SiteSetting.enable_s3_backups and ((!SiteSetting.s3_use_iam_profile and (SiteSetting.s3_access_key_id.blank? or SiteSetting.s3_secret_access_key.blank?)) or SiteSetting.s3_backup_bucket.blank?) + bad_keys = (SiteSetting.s3_access_key_id.blank? or SiteSetting.s3_secret_access_key.blank?) and !SiteSetting.s3_use_iam_profile + + return I18n.t('dashboard.s3_config_warning') if SiteSetting.enable_s3_uploads and (bad_keys or SiteSetting.s3_upload_bucket.blank?) + return I18n.t('dashboard.s3_backup_config_warning') if SiteSetting.enable_s3_backups and (bad_keys or SiteSetting.s3_backup_bucket.blank?) nil end