Skip to content
This repository has been archived by the owner on Oct 24, 2024. It is now read-only.

Commit

Permalink
Used the ENV variable AWS_MARKETPLACE_DEPLOYMENT to determine where t…
Browse files Browse the repository at this point in the history
…o look for the shop admin's AWS credentials before creating an Amazon S3 client
  • Loading branch information
phyninja committed Jan 14, 2022
1 parent 2f9dca5 commit 5521cb1
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 57 deletions.
62 changes: 17 additions & 45 deletions backend/logic/deploy/bucket/aws.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
const fs = require('fs')
const path = require('path')
const { trimStart, trimEnd } = require('lodash')
const AWS = require('aws-sdk/global')
const S3 = require('aws-sdk/clients/s3')
const { isConfigured } = require('@origin/dshop-validation/matrix')

const { guessContentType, walkDir } = require('../../../utils/filesystem')
const { assert } = require('../../../utils/validators')
const { BucketExistence } = require('../../../utils/enums')
const { NETWORK_ID_TO_NAME, BUCKET_PREFIX } = require('../../../utils/const')
const {
NETWORK_ID_TO_NAME,
AWS_MARKETPLACE_DEPLOYMENT,
BUCKET_PREFIX
} = require('../../../utils/const')
const { getLogger } = require('../../../utils/logger')

const log = getLogger('logic.deploy.bucket.aws')

let cachedClient = null
let tempCredentials = null

/**
* Check if AWS is configured and we can deploy to it
Expand All @@ -26,7 +28,7 @@ let tempCredentials = null
function isAvailable({ networkConfig, resourceSelection }) {
return (
resourceSelection.includes('aws-files') &&
isConfigured(networkConfig, 'aws-files')
(AWS_MARKETPLACE_DEPLOYMENT || isConfigured(networkConfig, 'aws-files'))
)
}

Expand All @@ -37,39 +39,19 @@ function isAvailable({ networkConfig, resourceSelection }) {
* @param args.networkConfig {Object} - Decrypted networkConfig object
*/

/*
Instead of getting the accessKeyId and secretAccessKey from the networkConfig
object, a call needs to be made to AWS.STS' assumeRole method. The result
of this call will be a AWS.Credentials object, whose keys will have
(temporary) values for accessKeyId and secretAccessKey
*/
async function configure({ networkConfig }) {
//Store the creds of the IAM user, if available in the 'networkConfig'
AWS.config = new AWS.Config({
accessKeyId: networkConfig.awsAccessKeyId,
secretAccessKey: networkConfig.awsSecretAccessKey
})

if (networkConfig.awsRoleARN) {
// The user wants DShop to use temporary credentials associated with an IAM Role. Ref: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/ChainableTemporaryCredentials.html#constructor-property
tempCredentials = new AWS.ChainableTemporaryCredentials({
params: {
RoleArn: networkConfig.awsRoleARN,
RoleSessionName: `DShop-aws-s3-session-${new Date().getTime()}`
}
})

await tempCredentials.getPromise().then(() => {
cachedClient = new S3({
apiVersion: '2006-03-01',
credentials: tempCredentials,
region: networkConfig.awsRegion // Optional
})
function configure({ networkConfig }) {
if (AWS_MARKETPLACE_DEPLOYMENT) {
//Use the credentials from the EC2 Instance metadata
cachedClient = new S3({
apiVersion: '2006-03-01',
region: networkConfig.awsRegion // Optional
})
} else {
// Use the credentials from the 'credentialProviderChain' (AWS.config or EC2 Instance metadata)
//Look up the shop admin's AWS credentials from the network config
cachedClient = new S3({
apiVersion: '2006-03-01',
accessKeyId: networkConfig.awsAccessKeyId,
secretAccessKey: networkConfig.awsSecretAccessKey,
region: networkConfig.awsRegion // Optional
})
}
Expand Down Expand Up @@ -127,19 +109,9 @@ async function deploy({ shop, networkConfig, OutputDir }) {
log.info(`Bucket ${bucketName} has been created.`)
}

await cachedClient
.upload({
Bucket: bucketName,
Key: 'key',
Body: 'test_string'
})
.promise()

log.debug(`Uploaded string to s3://${bucketName}/`)

// await uploadDirectory(bucketName, path.resolve(OutputDir, 'public'))
await uploadDirectory(bucketName, path.resolve(OutputDir, 'public'))

// log.debug(`Uploaded ${OutputDir} to s3://${bucketName}/`)
log.debug(`Uploaded ${OutputDir} to s3://${bucketName}/`)

return {
bucketName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
"AMIIdentifier": {
"Description": "The AMI Id to launch the EC2 instance from, if not the default ",
"Type": "String",
"Default": "ami-0d1a97b1f34f5ae1d"
"Default": "ami-083b7cfcc9a1dc0cf"
}
},

Expand Down
4 changes: 3 additions & 1 deletion backend/utils/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ const {
IPFS_GATEWAY, // IPFS gateway override
BUCKET_PREFIX = DEFAULT_BUCKET_PREFIX,
SERVICE_PREFIX = DEFAULT_SERVICE_PREFIX,
EXTERNAL_IP
EXTERNAL_IP,
AWS_MARKETPLACE_DEPLOYMENT //bool indicating whether the app is running from an AWS EC2 instance launched via the marketplace
} = process.env

/**
Expand Down Expand Up @@ -128,6 +129,7 @@ module.exports = {
BUCKET_PREFIX,
SERVICE_PREFIX,
EXTERNAL_IP,
AWS_MARKETPLACE_DEPLOYMENT,
EXTERNAL_IP_SERVICE_URL,
DEFAULT_INFRA_RESOURCES,
DEFAULT_AWS_REGION,
Expand Down
2 changes: 1 addition & 1 deletion packages/dshop-validation/resourceMatrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"supported": true,
"type": "files",
"depends": null,
"requiresConfig": []
"requiresConfig": ["awsAccessKeyId", "awsSecretAccessKey"]
},
{
"id": "ipfs-cluster",
Expand Down
40 changes: 31 additions & 9 deletions shop/src/pages/super-admin/networks/_Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ const _defaultShopConfigJSON = {
mailgunSmtpLogin: '',
mailgunSmtpPassword: '',
awsRegion: '',
awsRoleARN: '',
awsAccessKey: '',
awsAccessSecret: '',
upholdApi: '',
upholdClient: '',
upholdSecret: '',
Expand Down Expand Up @@ -102,7 +103,8 @@ function initialState() {
notificationEmail: '',
notificationEmailDisplayName: '',
defaultResourceSelection: [],
awsRoleARN: '',
awsAccessKey: '',
awsAccessSecret: '',
backendUrl,
infra: {},
infraErrors: [],
Expand Down Expand Up @@ -196,6 +198,32 @@ const NetworkForm = ({ onSave, network, feedback, className }) => {
shopConfig: state.fallbackShopConfig
})

/*
* The Networks form should ask the shop admin for their AWS Credentials only when the DShop DApp is not deployed on an EC2 instance launched via AWS Marketplace.
* Reason: When DShop is deployed with the help of the Marketplace solution, the shop admin's AWS credentials can be obtained programatically.
* Reference: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#instance-metadata-security-credentials
*/
const conditionallyRequestAWSCreds = () => {
if (process.env.AWS_MARKETPLACE_DEPLOYMENT) {
return
} else {
return (
<div className="form-row">
<div className="form-group col-md-6">
<label>AWS Access Key ID</label>
<input {...input('awsAccessKeyId')} />
{Feedback('awsAccessKeyId')}
</div>
<div className="form-group col-md-6">
<label>AWS Secret Access Key</label>
<PasswordField field="awsSecretAccessKey" input={input} />
{Feedback('awsSecretAccessKey')}
</div>
</div>
)
}
}

const ProcessorIdToEmailComp = {
sendgrid: SendgridModal,
aws: AWSModal,
Expand Down Expand Up @@ -406,13 +434,7 @@ const NetworkForm = ({ onSave, network, feedback, className }) => {
{Feedback('gcpCredentials')}
</div>
</div>
<div className="form-row">
<div className="form-group col-md-6">
<label>AWS Role ARN to access AWS resources</label>
<input {...input('awsRoleARN')} />
{Feedback('awsRoleARN')}
</div>
</div>
{conditionallyRequestAWSCreds()}
<div className="form-row">
<div className="form-group col-md-6">
<label>Discord Webhook</label>
Expand Down

0 comments on commit 5521cb1

Please sign in to comment.