From 4059b7efa22b735ac42fb55779bea11f474044ce Mon Sep 17 00:00:00 2001 From: "Michael J. Giarlo" Date: Thu, 2 May 2019 09:41:41 -0700 Subject: [PATCH] Inlined and adapted dependency code Includes: * Add `CMD` to Docker configuration to reflect the container's entrypoint * Split export and copy functionality into separate classes * Isolate AWS configuration within its own module * Move "glue" code to `index.js` * Set default value for S3 bucket * Add docker-compose configuration to mimic how we will run and configure the container in Fargate --- Dockerfile | 2 +- bin/backup | 2 +- config/default.js | 2 +- docker-compose.yml | 12 ++++++++++++ index.js | 9 +++++++++ src/CopyUsers.js | 26 ++++++++++++++++++++++++++ src/ExportUsers.js | 30 ++++++++++++++++++++++++++++++ src/backupUsers.js | 36 ------------------------------------ src/configureAWS.js | 12 ++++++++++++ 9 files changed, 92 insertions(+), 39 deletions(-) create mode 100644 docker-compose.yml create mode 100644 index.js create mode 100644 src/CopyUsers.js create mode 100644 src/ExportUsers.js delete mode 100644 src/backupUsers.js create mode 100644 src/configureAWS.js diff --git a/Dockerfile b/Dockerfile index 67ecaae..c9d64b8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,4 +6,4 @@ COPY . . RUN npm install -# TODO: Add CMD later once JavaScript package is in place +CMD ["bin/backup"] diff --git a/bin/backup b/bin/backup index ddf1677..8fe9dab 100755 --- a/bin/backup +++ b/bin/backup @@ -1,3 +1,3 @@ #!/usr/bin/env bash -npx babel-node src/backupUsers.js \ No newline at end of file +npx babel-node index.js \ No newline at end of file diff --git a/config/default.js b/config/default.js index e744f01..dc7025e 100644 --- a/config/default.js +++ b/config/default.js @@ -5,6 +5,6 @@ module.exports = { awsAccessKey: process.env.AWS_ACCESS_KEY_ID || '', awsAccessSecret: process.env.AWS_SECRET_ACCESS_KEY || '', awsRegion: process.env.AWS_REGION || 'us-west-2', - s3BucketUri: process.env.S3_BUCKET_URI || '', + s3BucketUri: process.env.S3_BUCKET_URI || 'sinopia-cognito-development', userPoolId: process.env.COGNITO_USER_POOL_ID || 'us-west-2_CGd9Wq136' } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6f5bcef --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: "3" +services: + app: + build: + context: . + environment: + AWS_REGION: ${AWS_REGION:-us-west-2} + AWS_ACCESS_KEY_ID: "${AWS_ACCESS_KEY_ID}" # add to .env file (DO NOT CHECK IN) + AWS_SECRET_ACCESS_KEY: "${AWS_SECRET_ACCESS_KEY}" # add to .env file (DO NOT CHECK IN) + COGNITO_USER_POOL_ID: ${COGNITO_USER_POOL_ID:-us-west-2_CGd9Wq136} + S3_BUCKET_URI: ${S3_BUCKET_URI:-sinopia-cognito-development} + command: bin/backup diff --git a/index.js b/index.js new file mode 100644 index 0000000..faba3c9 --- /dev/null +++ b/index.js @@ -0,0 +1,9 @@ +import ExportUsers from './src/ExportUsers' +import CopyUsers from './src/CopyUsers' + +const userBackup = async () => { + const userList = await new ExportUsers().export() + new CopyUsers(userList).copy() +} + +userBackup() diff --git a/src/CopyUsers.js b/src/CopyUsers.js new file mode 100644 index 0000000..2bfa127 --- /dev/null +++ b/src/CopyUsers.js @@ -0,0 +1,26 @@ +import AWS from 'aws-sdk' +import config from 'config' +import { configureAWS } from './configureAWS' + +export default class CopyUsers { + constructor(userList) { + AWS.config = configureAWS(AWS.config) + this.userListString = JSON.stringify(userList) + this.s3 = new AWS.S3() + this.objectKey = `${new Date().toISOString()}/${config.get('userPoolId')}.json` + } + + copy() { + this.s3.putObject({ + Body: this.userListString, + Bucket: config.get('s3BucketUri'), + Key: this.objectKey + }, error => { + if (error) { + console.error(`error copying backup to S3: ${error}`) + return + } + console.log('Users backed up to S3') + }) + } +} diff --git a/src/ExportUsers.js b/src/ExportUsers.js new file mode 100644 index 0000000..b24aa3e --- /dev/null +++ b/src/ExportUsers.js @@ -0,0 +1,30 @@ +import AWS from 'aws-sdk' +import config from 'config' +import { configureAWS } from './configureAWS' + +export default class ExportUsers { + constructor() { + AWS.config = configureAWS(AWS.config) + this.cognito = new AWS.CognitoIdentityServiceProvider() + } + + async export() { + const params = { UserPoolId: config.get('userPoolId') } + + const paginationCalls = async (exportedUsers = []) => { + const { Users = [], PaginationToken } = await this.cognito.listUsers(params).promise() + const combinedUsers = exportedUsers.concat(Users) + + if (PaginationToken) { + params.PaginationToken = PaginationToken + await paginationCalls(combinedUsers) + } + + return combinedUsers + } + + const userList = await paginationCalls() + console.log('Users exported from Cognito') + return userList + } +} diff --git a/src/backupUsers.js b/src/backupUsers.js deleted file mode 100644 index 419af35..0000000 --- a/src/backupUsers.js +++ /dev/null @@ -1,36 +0,0 @@ -import AWS from 'aws-sdk' -import { backupUsers } from 'cognito-backup-restore' -import config from 'config' -import fs from 'fs' - -AWS.config.update({ region: config.get('awsRegion') }) - -AWS.config.credentials = new AWS.Credentials({ - accessKeyId: config.get('awsAccessKey'), secretAccessKey: config.get('awsAccessSecret') -}) - -const cognito = new AWS.CognitoIdentityServiceProvider(); -const s3 = new AWS.S3() - -const timestamp = new Date().toISOString() -const filename = `${config.get('userPoolId')}.json` -const objectKey = `${timestamp}/${filename}` - -backupUsers(cognito, config.get('userPoolId'), '.') - .then(() => { - console.log(`Backup created`) - s3.putObject({ - Body: fs.readFileSync(filename, 'utf8'), - Bucket: config.get('s3BucketUri'), - Key: objectKey - }, error => { - if (error) { - console.error(`error copying backup to S3: ${error}`) - return - } - console.log('Backup copied to S3') - }) - }) - .catch(error => { - console.error(`error running backup: ${error}`) - }) diff --git a/src/configureAWS.js b/src/configureAWS.js new file mode 100644 index 0000000..067bd66 --- /dev/null +++ b/src/configureAWS.js @@ -0,0 +1,12 @@ +import AWS from 'aws-sdk' +import config from 'config' + +export const configureAWS = configuration => { + configuration.update({ region: config.get('awsRegion') }) + + configuration.credentials = new AWS.Credentials({ + accessKeyId: config.get('awsAccessKey'), secretAccessKey: config.get('awsAccessSecret') + }) + + return configuration +}