Skip to content

Commit

Permalink
Merge pull request #63 from CDLUC3/v1.1-beta
Browse files Browse the repository at this point in the history
V1.1 beta
  • Loading branch information
briri authored Oct 2, 2023
2 parents 59c700f + 9c76d13 commit 31fc85c
Show file tree
Hide file tree
Showing 23 changed files with 290 additions and 22 deletions.
Binary file modified .DS_Store
Binary file not shown.
17 changes: 17 additions & 0 deletions config/prd/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Sceptre will create an S3 bucket to store your CloudFormation templates. Define the name here or
# provide the name of an existing bucket.
#
template_bucket_name: 'uc3-dmp-hub-cf-bucket-cdluc3prd'
# Stack tags are attached to every AWS resource created by these CloudFormation templates
# with the exception of the Lambda functions and layers which are managed by AWS SAM.
#
stack_tags:
Program: 'uc3'
Service: 'dmp'
Subservice: 'hub'
Environment: 'prd'
CodeRepo: 'https://github.com/CDLUC3/dmp-hub-cfn'
Contact: 'briley'

# In the cdl-uc3-prd account devs must call cloudformation using a service role
cloudformation_service_role: 'arn:aws:iam::834750697783:role/uc3-prd-ops-cfn-service-role'
10 changes: 10 additions & 0 deletions config/prd/global/cert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
template:
path: cert.yaml
type: file

parameters:
HostedZoneId: !ssm_parameter /uc3/dmp/hub/prd/HostedZoneId

Domain: !stack_attr sceptre_user_data.domain

Env: !stack_attr sceptre_user_data.env
27 changes: 27 additions & 0 deletions config/prd/global/cloudfront.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
template:
path: 'cloudfront.yaml'
type: 'file'

dependencies:
- 'prd/regional/s3.yaml'

# NOTE: CloudFront can be slow to finish the creation/update process. The Distribution will go into
# a pending status and then can take some time before it is deployed. If your sceptre command
# appears to be stuck, this is most likely why, and you should let it complete.
parameters:
Domain: !stack_attr sceptre_user_data.domain

SsmPath: !stack_attr sceptre_user_data.ssm_path

CertificateArn: !stack_output prd/global/cert.yaml::CertificateArn

WafArn: !stack_output prd/global/waf.yaml::WafArn

S3LogBucketId: !stack_output prd/regional/s3.yaml::S3LogBucketId

S3CloudFrontBucketId: !stack_output prd/regional/s3.yaml::S3CloudFrontBucketId
S3CloudFrontBucketArn: !stack_output prd/regional/s3.yaml::S3CloudFrontBucketArn

CacheDefaultTtlSeconds: '180'
CacheMinTtlSeconds: '30'
CacheMaxTtlSeconds: '300' # 5 minutes
10 changes: 10 additions & 0 deletions config/prd/global/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# We need to override the default us-west-2 region here for CloudFront which must reside in us-east-1
region: 'us-east-1'

# Define reusable variables that can be referenced in template specific config files via:
# my_variable: !stack_attr sceptre_user_data.[variable]
sceptre_user_data:
env: 'prd'
domain: 'dmphub.uc3prd.cdlib.net'
hosted_zone: !ssm_parameter /uc3/dmp/hub/prd/HostedZoneId
ssm_path: '/uc3/dmp/hub/prd/'
16 changes: 16 additions & 0 deletions config/prd/global/route53.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
template:
path: 'route53.yaml'
type: 'file'

parameters:
HostedZoneId: !ssm_parameter /uc3/dmp/hub/prd/HostedZoneId

Env: !stack_attr sceptre_user_data.env
Domain: !stack_attr sceptre_user_data.domain
RecordType: 'A'

TargetName: !stack_output prd/global/cloudfront.yaml::CloudfrontDistroDomainName
# This HostedZone is the default for ALL CloudFront Distributions
TargetHostedZoneId: 'Z2FDTNDATAQYW2'

SetIdentifier: 'frobozz'
11 changes: 11 additions & 0 deletions config/prd/global/waf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
template:
path: 'waf.yaml'
type: 'file'

parameters:
# Specifies whether this is for a CLOUDFRONT distribution or for a REGIONAL application
Scope: 'CLOUDFRONT'
# Whether AWS WAF should store a sampling of the web requests that matched the rules.
SampledRequestsEnabled: 'true'
# Whether WAF sends metrics to Amazon CloudWatch.
CloudWatchMetricsEnabled: 'true'
48 changes: 48 additions & 0 deletions config/prd/regional/cognito.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
template:
path: 'cognito.yaml'
type: 'file'

dependencies:
- prd/global/route53.yaml

parameters:
HostedZoneId: !stack_attr sceptre_user_data.hosted_zone

Domain: !stack_attr sceptre_user_data.domain
Subdomain: 'auth'
Env: !stack_attr sceptre_user_data.env

CertificateArn: !stack_output prd/global/cert.yaml::CertificateArn

TagProgram: !stack_attr stack_tags.Program
TagService: !stack_attr stack_tags.Service
TagSubservice: !stack_attr stack_tags.Subservice
TagCodeRepo: !stack_attr stack_tags.CodeRepo
TagContact: !stack_attr stack_tags.Contact

DmptoolClientName: 'dmptool'

DmptoolCallbackUri: 'https://dmptool.org/callback'

OnlyAllowAdminsToCreateUsers: 'false'
UnusedAccountValidityDays: '14'
MinimumPasswordLength: '8'

TokenValidityUnits: 'minutes'
AccessTokenValidity: '10'
AuthSessionValidatyMinutes: '3'
IdTokenValidity: '7'
RefreshTokenValidity: '10080'

# NOTES:
# ----------------------------------------
#
# For ORCID integration via openID, check out:
# https://info.orcid.org/orcid-openid-connect-and-implicit-authentication/
# the issuer URL can be found here:
# https://orcid.org/.well-known/openid-configuration
#
# For Shibboleth integration, Mahjabeen said to reference this SAML file:
# https://samlproxy.ucop.edu/simplesaml/saml2/idp/metadata.php
# but apparently Cognito does not like it so instead an online tool called
# samltool and use the info from the above URL to build it.
19 changes: 19 additions & 0 deletions config/prd/regional/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

# Define reusable variables that can be referenced in template specific config files via:
# my_variable: !stack_attr sceptre_user_data.[variable]
sceptre_user_data:
vpc_id: !stack_output_external cdl-uc3-prd-vpc-stack::vpc
public_subnets:
- !stack_output_external cdl-uc3-prd-defaultsubnet-stack::defaultsubnet2a
- !stack_output_external cdl-uc3-prd-defaultsubnet-stack::defaultsubnet2b
- !stack_output_external cdl-uc3-prd-defaultsubnet-stack::defaultsubnet2c
private_subnets:
- !stack_output_external cdl-uc3-prd-privatesubnet-stack::privatesubnet2a
- !stack_output_external cdl-uc3-prd-privatesubnet-stack::privatesubnet2b
- !stack_output_external cdl-uc3-prd-privatesubnet-stack::privatesubnet2c

hosted_zone: !ssm_parameter /uc3/dmp/hub/prd/HostedZoneId

env: 'prd'
domain: 'dmphub.uc3prd.cdlib.net'
ssm_path: '/uc3/dmp/hub/prd/'
34 changes: 34 additions & 0 deletions config/prd/regional/dynamo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
template:
path: dynamo.yaml
type: file

parameters:
Env: !stack_attr sceptre_user_data.env

Domain: !stack_attr sceptre_user_data.domain

SsmPath: !stack_attr sceptre_user_data.ssm_path

# Dynamo settings
# See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html
DynamoTableClass: 'STANDARD'
DynamoEnableContributorInsights: 'true'
DynamoEnablePointInTimeRecovery: 'false'
DynamoBillingMode: 'PROVISIONED'
DynamoReadCapacityUnits: '16'
DynamoWriteCapacityUnits: '60'

hooks:
after_create:
# Add Provenance items to the Dynamo Table
- !cmd './seed_dynamo.sh prd DMPTool dmptool.org'
- !cmd './seed_dynamo.sh prd DMPHub dmphub.uc3prd.cdlib.net'

# Once the Dynamo table has been created, we can deploy our Lambdas and
# the API Gateway which are managed by AWS SAM.
# Args are: environment, domain, build the Lambda layer (boolean)
- !cmd 'cd ./src/sam && ruby sam_build_deploy.rb prd true true info'

# Build and deploy the React based DMP ID Landing Page to the CloudFront S3 bucket
# Args are: environment
- !cmd 'cd ./src/landing_page && ruby build_deply.sh prd'
14 changes: 14 additions & 0 deletions config/prd/regional/eventbridge.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
template:
path: eventbridge.yaml
type: file

parameters:
Env: !stack_attr sceptre_user_data.env

SsmPath: !stack_attr sceptre_user_data.ssm_path

DomainName: !stack_attr sceptre_user_data.domain

# Log and Archive retention
LogRetentionDays: '7'
ArchiveRetentionDays: '7'
10 changes: 10 additions & 0 deletions config/prd/regional/s3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
template:
path: s3.yaml
type: file

parameters:
Env: !stack_attr sceptre_user_data.env

SsmPath: !stack_attr sceptre_user_data.ssm_path

LogBucketObjectLifeSpan: '30'
22 changes: 22 additions & 0 deletions config/prd/regional/sqs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
template:
path: sqs.yaml
type: file

dependencies:
- 'prd/regional/s3.yaml'

parameters:
Env: !stack_attr sceptre_user_data.env
SsmPath: !stack_attr sceptre_user_data.ssm_path
AdminEmail: !ssm_parameter /uc3/dmp/hub/prd/AdminEmail

# SQS settings
# See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html
MessageRetentionSeconds: '7200' # 2 hours

DeadLetterRetentionSeconds: '259200' # 3 days

# Delay to allow underlying Lambdas to scale if necessary
DelaySeconds: '5'
# The number of times a message is delivered to the queue before being sent to dead-letter queue
MaxReceiveCount: '5'
Binary file modified src/.DS_Store
Binary file not shown.
8 changes: 4 additions & 4 deletions src/sam/functions/delete_dmp/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,22 @@ def self.process(event:, context:)
# Fail if the DMP ID is not a valid DMP ID
p_key = Uc3DmpId::Helper.path_parameter_to_pk(param: dmp_id)
p_key = Uc3DmpId::Helper.append_pk_prefix(p_key: p_key) unless p_key.nil?
return _respond(status: 400, errors: Uc3DmpId::MSG_DMP_INVALID_DMP_ID, event: event) if p_key.nil?
return _respond(status: 400, errors: Uc3DmpId::Helper::MSG_DMP_INVALID_DMP_ID, event: event) if p_key.nil?

_set_env(logger: logger)

# Fail if the Provenance could not be loaded
claim = event.fetch('requestContext', {}).fetch('authorizer', {})['claims']
provenance = Uc3DmpProvenance::Finder.from_lambda_cotext(identity: claim, logger: logger)
return _respond(status: 403, errors: Uc3DmpId::MSG_DMP_FORBIDDEN, event: event) if provenance.nil?
return _respond(status: 403, errors: Uc3DmpId::Helper::MSG_DMP_FORBIDDEN, event: event) if provenance.nil?

# Update the DMP ID
resp = Uc3DmpId::Deleter.tombstone(provenance: provenance, p_key: p_key, logger: logger)
return _respond(status: 400, errors: Uc3DmpId::MSG_DMP_NO_DMP_ID) if resp.nil?
return _respond(status: 400, errors: Uc3DmpId::Helper::MSG_DMP_NO_DMP_ID) if resp.nil?

_respond(status: 200, items: [resp], event: event)
rescue Uc3DmpId::DeleterError => e
_respond(status: 400, errors: [Uc3DmpId::MSG_DMP_NO_DMP_ID, e.message], event: event)
_respond(status: 400, errors: [Uc3DmpId::Helper::MSG_DMP_NO_DMP_ID, e.message], event: event)
rescue StandardError => e
logger.error(message: e.message, details: e.backtrace)
Uc3DmpApiCore::Notifier.notify_administrator(source: SOURCE, details: { dmp_id: p_key }, event: event)
Expand Down
2 changes: 1 addition & 1 deletion src/sam/functions/get_dmp/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def self.process(event:, context:)
# Fail if the DMP ID is not a valid DMP ID
p_key = Uc3DmpId::Helper.path_parameter_to_pk(param: dmp_id)
p_key = Uc3DmpId::Helper.append_pk_prefix(p_key: p_key) unless p_key.nil?
return _respond(status: 400, errors: Uc3DmpId::MSG_DMP_INVALID_DMP_ID, event: event) if p_key.nil?
return _respond(status: 400, errors: Uc3DmpId::Helper::MSG_DMP_INVALID_DMP_ID, event: event) if p_key.nil?

# Fetch SSM parameters and set them in the ENV
_set_env(logger: logger)
Expand Down
6 changes: 3 additions & 3 deletions src/sam/functions/get_dmps/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ def self.process(event:, context:)
return _respond(status: 403, errors: Uc3DmpId::MSG_DMP_FORBIDDEN, event: event) if provenance.nil?

resp = Uc3DmpId::Finder.search_dmps(args: params, logger: logger)
return _respond(status: 400, errors: Uc3DmpId::MSG_DMP_NO_DMP_ID) if resp.nil?
return _respond(status: 404, errors: Uc3DmpId::MSG_DMP_NOT_FOUND) if resp.empty?
return _respond(status: 400, errors: Uc3DmpId::Helper::MSG_DMP_NO_DMP_ID) if resp.nil?
return _respond(status: 404, errors: Uc3DmpId::Helper::MSG_DMP_NOT_FOUND) if resp.empty?

logger.debug(message: 'Found the following results:', details: resp) if logger.respond_to?(:debug)
_respond(status: 200, items: [resp], event: event)
rescue Uc3DmpId::FinderError => e
_respond(status: 400, errors: [Uc3DmpId::MSG_DMP_NO_DMP_ID, e.message], event: event)
_respond(status: 400, errors: [Uc3DmpId::Helper::MSG_DMP_NO_DMP_ID, e.message], event: event)
rescue StandardError => e
logger.error(message: e.message, details: e.backtrace)
deets = { message: e.message, params: params }
Expand Down
6 changes: 3 additions & 3 deletions src/sam/functions/post_dmps/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ def self.process(event:, context:)
# Fail if the Provenance could not be loaded
claim = event.fetch('requestContext', {}).fetch('authorizer', {})['claims']
provenance = Uc3DmpProvenance::Finder.from_lambda_cotext(identity: claim, logger: logger)
return _respond(status: 403, errors: Uc3DmpId::MSG_DMP_FORBIDDEN, event: event) if provenance.nil?
return _respond(status: 403, errors: Uc3DmpId::Helper::MSG_DMP_FORBIDDEN, event: event) if provenance.nil?

# Register a new DMP ID
resp = Uc3DmpId::Creator.create(provenance: provenance, json: json, logger: logger)
return _respond(status: 400, errors: Uc3DmpId::MSG_DMP_NO_DMP_ID) if resp.nil?
return _respond(status: 400, errors: Uc3DmpId::Helper::MSG_DMP_NO_DMP_ID) if resp.nil?

_respond(status: 201, items: [resp], event: event)
rescue Uc3DmpId::CreatorError => e
_respond(status: 400, errors: [Uc3DmpId::MSG_DMP_NO_DMP_ID, e.message], event: event)
_respond(status: 400, errors: [Uc3DmpId::Helper::MSG_DMP_NO_DMP_ID, e.message], event: event)
rescue StandardError => e
logger.error(message: e.message, details: e.backtrace)
deets = { message: e.message, body: body }
Expand Down
4 changes: 2 additions & 2 deletions src/sam/functions/post_narratives/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ def self.process(event:, context:)
# Fail if the Provenance could not be loaded
claim = event.fetch('requestContext', {}).fetch('authorizer', {})['claims']
provenance = Uc3DmpProvenance::Finder.from_lambda_cotext(identity: claim, logger: logger)
return _respond(status: 403, errors: Uc3DmpId::MSG_DMP_FORBIDDEN, event: event) if provenance.nil?
return _respond(status: 403, errors: Uc3DmpId::Helper::MSG_DMP_FORBIDDEN, event: event) if provenance.nil?

# Make sure there is a DMP ID for the narrative to be attached to!
dmp = Uc3DmpId::Finder.by_pk(p_key: params[:dmp_id], logger: logger)
return _respond(status: 403, errors: [Uc3DmpId::MSG_DMP_FORBIDDEN], event: event) if dmp.nil?
return _respond(status: 403, errors: [Uc3DmpId::Helper::MSG_DMP_FORBIDDEN], event: event) if dmp.nil?

# Store the document in S3 Bucket
object_key = Uc3DmpS3::Client.put_narrative(document: params[:payload], dmp_id: params[:dmp_id], base64: params[:base64encoded])
Expand Down
8 changes: 4 additions & 4 deletions src/sam/functions/put_dmp/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,24 @@ def self.process(event:, context:)
# Fail if the DMP ID is not a valid DMP ID
p_key = Uc3DmpId::Helper.path_parameter_to_pk(param: dmp_id)
p_key = Uc3DmpId::Helper.append_pk_prefix(p_key: p_key) unless p_key.nil?
return _respond(status: 400, errors: Uc3DmpId::MSG_DMP_INVALID_DMP_ID, event: event) if p_key.nil?
return _respond(status: 400, errors: Uc3DmpId::Helper::MSG_DMP_INVALID_DMP_ID, event: event) if p_key.nil?

_set_env(logger: logger)

# Fail if the Provenance could not be loaded
claim = event.fetch('requestContext', {}).fetch('authorizer', {})['claims']
provenance = Uc3DmpProvenance::Finder.from_lambda_cotext(identity: claim, logger: logger)
return _respond(status: 403, errors: Uc3DmpId::MSG_DMP_FORBIDDEN, event: event) if provenance.nil?
return _respond(status: 403, errors: Uc3DmpId::Helper::MSG_DMP_FORBIDDEN, event: event) if provenance.nil?

logger.debug(message: "Attempting update to PK: #{p_key}", details: json) if logger.respond_to?(:debug)

# Update the DMP ID
resp = Uc3DmpId::Updater.update(logger: logger, provenance: provenance, p_key: p_key, json: json)
return _respond(status: 400, errors: Uc3DmpId::MSG_DMP_NO_DMP_ID) if resp.nil?
return _respond(status: 400, errors: Uc3DmpId::Helper::MSG_DMP_NO_DMP_ID) if resp.nil?

_respond(status: 200, items: [resp], event: event)
rescue Uc3DmpId::UpdaterError => e
_respond(status: 400, errors: [Uc3DmpId::MSG_DMP_NO_DMP_ID, e.message], event: event)
_respond(status: 400, errors: [Uc3DmpId::Helper::MSG_DMP_NO_DMP_ID, e.message], event: event)
rescue StandardError => e
logger.error(message: e.message, details: e.backtrace)
deets = { message: e.message, dmp_id: p_key, body: body }
Expand Down
Loading

0 comments on commit 31fc85c

Please sign in to comment.