From e2e19e73e9573270cab78bfef2e18965344e297f Mon Sep 17 00:00:00 2001 From: jtrollin Date: Thu, 21 May 2020 12:39:29 -0400 Subject: [PATCH] updated the stack to use secrets manageer to store the database password so it will no longer be visable in the stack or the config.php file --- templates/00-master.yaml | 57 ++++++------ templates/03-rds.yaml | 48 ++++++----- templates/04-web.yaml | 182 +++++++++++++++++++++++---------------- 3 files changed, 168 insertions(+), 119 deletions(-) diff --git a/templates/00-master.yaml b/templates/00-master.yaml index fcbc589..6352da9 100644 --- a/templates/00-master.yaml +++ b/templates/00-master.yaml @@ -56,7 +56,7 @@ Metadata: - DatabaseEncrpytedBoolean - DatabaseCmk - DatabaseMasterUsername - - DatabaseMasterPassword + # - DatabaseMasterPassword - DatabaseName - Label: default: Caching Tier @@ -95,8 +95,8 @@ Metadata: default: DB Instance Class DatabaseMasterUsername: default: DB Master Username - DatabaseMasterPassword: - default: DB Master Password + # DatabaseMasterPassword: + # default: DB Master Password DatabaseName: default: DB Name EfsCmk: @@ -319,14 +319,14 @@ Parameters: MinLength: 1 Type: String Default: moodle - DatabaseMasterPassword: - AllowedPattern: ^([a-zA-Z0-9`~!#$%^&*()_+,\\-])*$ - ConstraintDescription: Must be letters (upper or lower), numbers, spaces, and these special characters `~!#$%^&*()_+,- - Description: The Amazon RDS master password. Letters, numbers, spaces, and these special characters `~!#$%^&*()_+,- - MaxLength: 41 - MinLength: 8 - NoEcho: true - Type: String + # DatabaseMasterPassword: + # AllowedPattern: ^([a-zA-Z0-9`~!#$%^&*()_+,\\-])*$ + # ConstraintDescription: Must be letters (upper or lower), numbers, spaces, and these special characters `~!#$%^&*()_+,- + # Description: The Amazon RDS master password. Letters, numbers, spaces, and these special characters `~!#$%^&*()_+,- + # MaxLength: 41 + # MinLength: 8 + # NoEcho: true + # Type: String DatabaseName: AllowedPattern: ^([a-zA-Z0-9]*)$ Description: The Amazon RDS master database name. @@ -806,6 +806,15 @@ Conditions: !Equals [ true, !Ref UseCloudFrontBoolean ] Resources: + MyRDSInstanceSecret: + Type: AWS::SecretsManager::Secret + Properties: + Description: 'This is the secret for my RDS instance' + GenerateSecretString: + SecretStringTemplate: !Sub '{"username": "${DatabaseMasterUsername}"}' + GenerateStringKey: 'password' + PasswordLength: 16 + ExcludeCharacters: '"@/\' vpc: Type: AWS::CloudFormation::Stack Properties: @@ -900,16 +909,16 @@ Resources: !GetAtt [ vpc, Outputs.Vpc ] TemplateURL: https://s3.amazonaws.com/aws-refarch/moodle/latest/templates/03-publicalb.yaml rds: - DependsOn: [ securitygroups, securitygroups ] + DependsOn: [ securitygroups ] Type: AWS::CloudFormation::Stack Properties: Parameters: DatabaseInstanceType: !Ref DatabaseInstanceType - DatabaseMasterUsername: - !Ref DatabaseMasterUsername - DatabaseMasterPassword: - !Ref DatabaseMasterPassword + # DatabaseMasterUsername: + # !Ref DatabaseMasterUsername + MyRDSInstanceSecretArn: + !Ref MyRDSInstanceSecret DatabaseName: !Ref DatabaseName DatabaseEncrpytedBoolean: @@ -989,10 +998,10 @@ Resources: Parameters: DatabaseClusterEndpointAddress: !GetAtt [ rds, Outputs.DatabaseClusterEndpointAddress ] - DatabaseMasterUsername: - !Ref DatabaseMasterUsername - DatabaseMasterPassword: - !Ref DatabaseMasterPassword + # DatabaseMasterUsername: + # !Ref DatabaseMasterUsername + MyRDSInstanceSecretArn: + !Ref MyRDSInstanceSecret DatabaseName: !Ref DatabaseName ElasticFileSystem: @@ -1032,10 +1041,10 @@ Resources: Parameters: DatabaseClusterEndpointAddress: !GetAtt [ rds, Outputs.DatabaseClusterEndpointAddress ] - DatabaseMasterUsername: - !Ref DatabaseMasterUsername - DatabaseMasterPassword: - !Ref DatabaseMasterPassword + # DatabaseMasterUsername: + # !Ref DatabaseMasterUsername + MyRDSInstanceSecretArn: + !Ref MyRDSInstanceSecret DatabaseName: !Ref DatabaseName ElasticFileSystem: diff --git a/templates/03-rds.yaml b/templates/03-rds.yaml index 775756e..547e89e 100644 --- a/templates/03-rds.yaml +++ b/templates/03-rds.yaml @@ -10,8 +10,8 @@ Metadata: default: Database Parameters Parameters: - DatabaseInstanceType - - DatabaseMasterUsername - - DatabaseMasterPassword + # - DatabaseMasterUsername + # - DatabaseMasterPassword - DatabaseName - DatabaseEncrpytedBoolean - DatabaseCmk @@ -25,10 +25,10 @@ Metadata: default: AWS KMS Customer Master Key (CMK) to encrypt DB DatabaseInstanceType: default: DB Instance Class - DatabaseMasterUsername: - default: DB Master Username - DatabaseMasterPassword: - default: DB Master Password + # DatabaseMasterUsername: + # default: DB Master Username + # DatabaseMasterPassword: + # default: DB Master Password DatabaseName: default: DB Name DatabaseSecurityGroup: @@ -62,20 +62,22 @@ Parameters: Default: db.r4.large Description: The Amazon RDS database instance class. Type: String - DatabaseMasterUsername: - AllowedPattern: ^([a-zA-Z0-9]*)$ - Description: The Amazon RDS master username. - ConstraintDescription: Must contain only alphanumeric characters and be at least 8 characters. - MaxLength: 16 - MinLength: 1 - Type: String - DatabaseMasterPassword: - AllowedPattern: ^([a-z0-9A-Z`~!#$%^&*()_+,\\-])*$ - ConstraintDescription: Must be letters (upper or lower), numbers, and these special characters '_'`~!#$%^&*()_+,- - Description: The Amazon RDS master password. - MaxLength: 41 - MinLength: 8 - NoEcho: true + # DatabaseMasterUsername: + # AllowedPattern: ^([a-zA-Z0-9]*)$ + # Description: The Amazon RDS master username. + # ConstraintDescription: Must contain only alphanumeric characters and be at least 8 characters. + # MaxLength: 16 + # MinLength: 1 + # Type: String + # DatabaseMasterPassword: + # AllowedPattern: ^([a-z0-9A-Z`~!#$%^&*()_+,\\-])*$ + # ConstraintDescription: Must be letters (upper or lower), numbers, and these special characters '_'`~!#$%^&*()_+,- + # Description: The Amazon RDS master password. + # MaxLength: 41 + # MinLength: 8 + # NoEcho: true + # Type: String + MyRDSInstanceSecretArn: Type: String DatabaseName: AllowedPattern: ^([a-zA-Z0-9]*)$ @@ -142,7 +144,6 @@ Conditions: !Equals ['', !Ref DatabaseCmk] Resources: - DatabaseCluster: Type: AWS::RDS::DBCluster Properties: @@ -153,8 +154,8 @@ Resources: DBClusterParameterGroupName: default.aurora-postgresql11 KmsKeyId: !If [ UseAWS-ManagedCMK, !Ref 'AWS::NoValue', !Ref DatabaseCmk ] - MasterUsername: !Ref DatabaseMasterUsername - MasterUserPassword: !Ref DatabaseMasterPassword + MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref MyRDSInstanceSecretArn, ':SecretString:username}}' ]] + MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref MyRDSInstanceSecretArn, ':SecretString:password}}' ]] Port: 5432 StorageEncrypted: !Ref DatabaseEncrpytedBoolean Tags: @@ -231,4 +232,5 @@ Outputs: Value: !Ref DataSubnetGroup DatabaseClusterEndpointAddress: Value: !GetAtt DatabaseCluster.Endpoint.Address + diff --git a/templates/04-web.yaml b/templates/04-web.yaml index 4034109..3ceb151 100644 --- a/templates/04-web.yaml +++ b/templates/04-web.yaml @@ -30,8 +30,8 @@ Metadata: Parameters: - DatabaseClusterEndpointAddress - DatabaseName - - DatabaseMasterUsername - - DatabaseMasterPassword + # - DatabaseMasterUsername + # - DatabaseMasterPassword - DatabaseClusterEndpointAddress - ElastiCacheClusterEndpointAddress - Label: @@ -41,10 +41,10 @@ Metadata: ParameterLabels: DatabaseClusterEndpointAddress: default: DB Cluster Endpoint Address - DatabaseMasterUsername: - default: DB Master Username - DatabaseMasterPassword: - default: DB Master Password + # DatabaseMasterUsername: + # default: DB Master Username + # DatabaseMasterPassword: + # default: DB Master Password DatabaseName: default: DB Name ElastiCacheClusterEndpointAddress: @@ -84,20 +84,22 @@ Parameters: DatabaseClusterEndpointAddress: Description: The RDS cluster endpoint address. Type: String - DatabaseMasterUsername: - AllowedPattern: ^([a-zA-Z0-9]*)$ - Description: The Amazon RDS master username. - ConstraintDescription: Must contain only alphanumeric characters and be at least 8 characters. - MaxLength: 16 - MinLength: 1 - Type: String - DatabaseMasterPassword: - AllowedPattern: ^([a-z0-9A-Z`~!#$%^&*()_+,\\-])*$ - ConstraintDescription: Must be letters (upper or lower), numbers, and these special characters '_'`~!#$%^&*()_+,- - Description: The Amazon RDS master password. - MaxLength: 41 - MinLength: 8 - NoEcho: true + # DatabaseMasterUsername: + # AllowedPattern: ^([a-zA-Z0-9]*)$ + # Description: The Amazon RDS master username. + # ConstraintDescription: Must contain only alphanumeric characters and be at least 8 characters. + # MaxLength: 16 + # MinLength: 1 + # Type: String + # DatabaseMasterPassword: + # AllowedPattern: ^([a-z0-9A-Z`~!#$%^&*()_+,\\-])*$ + # ConstraintDescription: Must be letters (upper or lower), numbers, and these special characters '_'`~!#$%^&*()_+,- + # Description: The Amazon RDS master password. + # MaxLength: 41 + # MinLength: 8 + # NoEcho: true + # Type: String + MyRDSInstanceSecretArn: Type: String DatabaseName: AllowedPattern: ^([a-zA-Z0-9]*)$ @@ -353,6 +355,15 @@ Resources: - autoscaling:DescribeLifecycleHooks Resource: - arn:aws:autoscaling:*:*:* + - PolicyName: SecretManager + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - secretsmanager:GetSecretValue + Resource: + - !Ref MyRDSInstanceSecretArn Logs: Type: AWS::Logs::LogGroup DeletionPolicy: Retain @@ -565,66 +576,93 @@ Resources: files: /tmp/config.php: content: !Sub | - dbtype = 'pgsql'; - $CFG->dblibrary = 'native'; - $CFG->dbhost = '${DatabaseClusterEndpointAddress}'; - $CFG->dbname = '${DatabaseName}'; - $CFG->dbuser = '${DatabaseMasterUsername}'; - $CFG->dbpass = '${DatabaseMasterPassword}'; - $CFG->prefix = 'mdl_'; - $CFG->lang = '${MoodleLocale}'; - $CFG->dboptions = array( - 'dbpersist' => false, - 'dbsocket' => false, - 'dbport' => '', - 'dbhandlesoptions' => false, - 'dbcollation' => 'utf8mb4_unicode_ci', - ); - // Hostname definition // - $hostname = '${DomainName}'; - if ($hostname == '') { - $hostwithprotocol = '${PublicAlbHostname}'; - } - else { - $hostwithprotocol = 'https://' . strtolower($hostname); - } - $CFG->wwwroot = strtolower($hostwithprotocol); - $CFG->sslproxy = (substr($hostwithprotocol,0,5)=='https' ? true : false); - // Moodledata location // - $CFG->dataroot = '/var/www/moodle/data'; - $CFG->tempdir = '/var/www/moodle/temp'; - $CFG->cachedir = '/var/www/moodle/cache'; - $CFG->localcachedir = '/var/www/moodle/local'; - $CFG->directorypermissions = 02777; - $CFG->admin = 'admin'; - // Configure Session Cache - $SessionEndpoint = '${ElastiCacheClusterEndpointAddress}'; - if ($SessionEndpoint != '') { - $CFG->dbsessions = false; - $CFG->session_handler_class = '\core\session\memcached'; - $CFG->session_memcached_save_path = $SessionEndpoint; - $CFG->session_memcached_prefix = 'memc.sess.key.'; - $CFG->session_memcached_acquire_lock_timeout = 120; - $CFG->session_memcached_lock_expire = 7100; - $CFG->session_memcached_lock_retry_sleep = 150; - } - //@error_reporting(E_ALL | E_STRICT); // NOT FOR PRODUCTION SERVERS! - //@ini_set('display_errors', '1'); // NOT FOR PRODUCTION SERVERS! - //$CFG->debug = (E_ALL | E_STRICT); // === DEBUG_DEVELOPER - NOT FOR PRODUCTION SERVERS! - //$CFG->debugdisplay = 1; - require_once(__DIR__ . '/lib/setup.php'); - // END OF CONFIG // - ?> + '2017-10-17', + 'region' => 'us-east-1', + ]); + + $secretName = '${MyRDSInstanceSecretArn}'; + + try { + $result = $client->getSecretValue([ + 'SecretId' => $secretName, + ]); + + } catch (AwsException $e) { + $error = $e->getAwsErrorCode(); + } + // Decrypts secret using the associated KMS CMK. + // Depending on whether the secret is a string or binary, one of these fields will be populated. + if (isset($result['SecretString'])) { + $secret = $result['SecretString']; + } + $CFG = new stdClass; + $CFG->dbtype = 'pgsql'; + $CFG->dblibrary = 'native'; + $CFG->dbhost = '${DatabaseClusterEndpointAddress}'; + $CFG->dbname = '${DatabaseName}'; + $CFG->dbuser = json_decode($secret)->{'username'}; + $CFG->dbpass = json_decode($secret)->{'password'}; + $CFG->prefix = 'mdl_'; + $CFG->lang = '${MoodleLocale}'; + $CFG->dboptions = array( + 'dbpersist' => false, + 'dbsocket' => false, + 'dbport' => '', + 'dbhandlesoptions' => false, + 'dbcollation' => 'utf8mb4_unicode_ci', + ); + // Hostname definition // + $hostname = '${DomainName}'; + if ($hostname == '') { + $hostwithprotocol = '${PublicAlbHostname}'; + } + else { + $hostwithprotocol = 'https://' . strtolower($hostname); + } + $CFG->wwwroot = strtolower($hostwithprotocol); + $CFG->sslproxy = (substr($hostwithprotocol,0,5)=='https' ? true : false); + // Moodledata location // + $CFG->dataroot = '/var/www/moodle/data'; + $CFG->tempdir = '/var/www/moodle/temp'; + $CFG->cachedir = '/var/www/moodle/cache'; + $CFG->localcachedir = '/var/www/moodle/local'; + $CFG->directorypermissions = 02777; + $CFG->admin = 'admin'; + // Configure Session Cache + $SessionEndpoint = '${ElastiCacheClusterEndpointAddress}'; + if ($SessionEndpoint != '') { + $CFG->dbsessions = false; + $CFG->session_handler_class = '\core\session\memcached'; + $CFG->session_memcached_save_path = $SessionEndpoint; + $CFG->session_memcached_prefix = 'memc.sess.key.'; + $CFG->session_memcached_acquire_lock_timeout = 120; + $CFG->session_memcached_lock_expire = 7100; + $CFG->session_memcached_lock_retry_sleep = 150; + } + //@error_reporting(E_ALL | E_STRICT); // NOT FOR PRODUCTION SERVERS! + //@ini_set('display_errors', '1'); // NOT FOR PRODUCTION SERVERS! + //$CFG->debug = (E_ALL | E_STRICT); // === DEBUG_DEVELOPER - NOT FOR PRODUCTION SERVERS! + //$CFG->debugdisplay = 1; + require_once(__DIR__ . '/lib/setup.php'); + // END OF CONFIG // + ?> mode: '000755' owner: root group: root + /tmp/install_moodle.sh: content: !Sub | #!/bin/bash -xe wget -O /tmp/moodle.tgz https://download.moodle.org/download.php/direct/stable38/moodle-3.8.3.tgz tar -xvzf /tmp/moodle.tgz --strip-components=1 -C /var/www/moodle/html/ + wget -O /var/www/moodle/html/lib/aws.phar https://docs.aws.amazon.com/aws-sdk-php/v3/download/aws.phar cp /tmp/config.php /var/www/moodle/html/config.php chown -R root:apache /var/www/moodle/html chown -R apache:apache /var/www/moodle/local