diff --git a/.env b/.env deleted file mode 100644 index 57f7e5d..0000000 --- a/.env +++ /dev/null @@ -1,7 +0,0 @@ -# Domain Configuration -AWS_DOMAIN_NAME=dev-clock.taylormadetech.net -AWS_BASE_DOMAIN=taylormadetech.net -AWS_HOSTED_ZONE_ID=Z08476952AAJG5D55EAB6 - -# Environment -NODE_ENV=development diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7844547..e650923 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -36,6 +36,11 @@ jobs: - name: Build Vite application run: npm run build + env: + VITE_ENVIRONMENT: development # Explicitly set for clarity, though build often defaults to 'development' if not 'production' + VITE_AWS_DOMAIN_NAME_DEV: ${{ secrets.AWS_DOMAIN_NAME_DEV }} + VITE_AWS_BASE_DOMAIN_DEV: ${{ secrets.AWS_BASE_DOMAIN_DEV }} + VITE_AWS_HOSTED_ZONE_ID_DEV: ${{ secrets.AWS_HOSTED_ZONE_ID_DEV }} - name: Compile CDK TypeScript run: npx tsc @@ -43,17 +48,17 @@ jobs: - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.AWS_REGION }} # e.g., us-east-1 + role-to-assume: ${{ secrets.ROLE_TO_ASSUME }} + role-session-name: ${{ secrets.ROLE_SESSION_NAME }} + aws-region: ${{ secrets.AWS_REGION }} - name: Deploy CDK Stack (Development) run: npm run cdk -- deploy --all -c environment=development --require-approval never env: - # DEV_DOMAIN_NAME: ${{ secrets.DEV_DOMAIN_NAME }} - # DEV_BASE_DOMAIN_NAME: ${{ secrets.DEV_BASE_DOMAIN_NAME }} - # DEV_HOSTED_ZONE_ID: ${{ secrets.DEV_HOSTED_ZONE_ID }} CI: true + AWS_DOMAIN_NAME_DEV: ${{ secrets.AWS_DOMAIN_NAME_DEV }} + AWS_BASE_DOMAIN_DEV: ${{ secrets.AWS_BASE_DOMAIN_DEV }} + AWS_HOSTED_ZONE_ID_DEV: ${{ secrets.AWS_HOSTED_ZONE_ID_DEV }} deploy_prod: name: Deploy to Production @@ -86,6 +91,11 @@ jobs: - name: Build Vite application run: npm run build + env: + VITE_ENVIRONMENT: production + VITE_AWS_DOMAIN_NAME_PROD: ${{ secrets.AWS_DOMAIN_NAME_PROD }} + VITE_AWS_BASE_DOMAIN_PROD: ${{ secrets.AWS_BASE_DOMAIN_PROD }} + VITE_AWS_HOSTED_ZONE_ID_PROD: ${{ secrets.AWS_HOSTED_ZONE_ID_PROD }} - name: Compile CDK TypeScript run: npx tsc @@ -93,17 +103,14 @@ jobs: - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.AWS_REGION }} # Ensure this is your production region or use a specific secret like secrets.PROD_AWS_REGION + role-to-assume: ${{ secrets.ROLE_TO_ASSUME }} + role-session-name: ${{ secrets.ROLE_SESSION_NAME }} + aws-region: ${{ secrets.AWS_REGION }} - name: Deploy CDK Stack (Production) run: npm run cdk -- deploy --all -c environment=production --require-approval never env: - # Ensure your config/index.ts can resolve values for 'production' - # or pass them via -c context or environment variables if needed, e.g., - # PROD_DOMAIN_NAME: ${{ secrets.PROD_DOMAIN_NAME }} - # PROD_BASE_DOMAIN_NAME: ${{ secrets.PROD_BASE_DOMAIN_NAME }} - # PROD_HOSTED_ZONE_ID: ${{ secrets.PROD_HOSTED_ZONE_ID }} - # Ensure these secrets are configured in your GitHub repository settings if they are required by your CDK stack for production. CI: true + AWS_DOMAIN_NAME_PROD: ${{ secrets.AWS_DOMAIN_NAME_PROD }} + AWS_BASE_DOMAIN_PROD: ${{ secrets.AWS_BASE_DOMAIN_PROD }} + AWS_HOSTED_ZONE_ID_PROD: ${{ secrets.AWS_HOSTED_ZONE_ID_PROD }} diff --git a/config/index.ts b/config/index.ts index 2068844..0eb3800 100644 --- a/config/index.ts +++ b/config/index.ts @@ -8,23 +8,35 @@ export type DeploymentConfig = { }; export function getConfig(env: string = 'development', envVars: Record): DeploymentConfig { + // Ensure the environment is valid, default to 'development' if not provided or invalid + const resolvedEnv = (env === 'production' || env === 'development') ? env : 'development'; + + // Define the configuration for each environment, strictly relying on environment variables const configs: Record = { development: { environment: 'development', aws: { - domainName: envVars.VITE_AWS_DOMAIN_NAME || envVars.AWS_DOMAIN_NAME || 'dev-clock.taylormadetech.net', - baseDomainName: envVars.VITE_AWS_BASE_DOMAIN || envVars.AWS_BASE_DOMAIN || 'taylormadetech.net', - hostedZoneId: envVars.VITE_AWS_HOSTED_ZONE_ID || envVars.AWS_HOSTED_ZONE_ID || 'Z08476952AAJG5D55EAB6' + // Prioritize AWS_DOMAIN_NAME for CI/CD context, fall back to VITE_AWS_DOMAIN_NAME if needed (e.g., for local Vite dev) + domainName: envVars.AWS_DOMAIN_NAME_DEV || envVars.VITE_AWS_DOMAIN_NAME_DEV || '', + baseDomainName: envVars.AWS_BASE_DOMAIN_DEV || envVars.VITE_AWS_BASE_DOMAIN_DEV || '', + hostedZoneId: envVars.AWS_HOSTED_ZONE_ID_DEV || envVars.VITE_AWS_HOSTED_ZONE_ID_DEV || '' } }, production: { environment: 'production', aws: { - domainName: envVars.VITE_AWS_DOMAIN_NAME || envVars.AWS_DOMAIN_NAME || 'clock.taylormadetech.net', - baseDomainName: envVars.VITE_AWS_BASE_DOMAIN || envVars.AWS_BASE_DOMAIN || 'taylormadetech.net', - hostedZoneId: envVars.VITE_AWS_HOSTED_ZONE_ID || envVars.AWS_HOSTED_ZONE_ID || 'Z08476952AAJG5D55EAB6' + domainName: envVars.AWS_DOMAIN_NAME_PROD || envVars.VITE_AWS_DOMAIN_NAME_PROD || '', + baseDomainName: envVars.AWS_BASE_DOMAIN_PROD || envVars.VITE_AWS_BASE_DOMAIN_PROD || '', + hostedZoneId: envVars.AWS_HOSTED_ZONE_ID_PROD || envVars.VITE_AWS_HOSTED_ZONE_ID_PROD || '' } } }; - return configs[env] || configs.development; + + // Add a check to ensure required variables are present for the chosen environment + const currentConfig = configs[resolvedEnv]; + if (!currentConfig.aws.domainName || !currentConfig.aws.baseDomainName || !currentConfig.aws.hostedZoneId) { + throw new Error(`Missing required AWS environment variables for ${resolvedEnv} environment. Please ensure AWS_DOMAIN_NAME_${resolvedEnv.toUpperCase()}, AWS_BASE_DOMAIN_${resolvedEnv.toUpperCase()}, and AWS_HOSTED_ZONE_ID_${resolvedEnv.toUpperCase()} are set.`); + } + + return currentConfig; } diff --git a/github-actions-iam-user.yml b/github-actions-iam-user.yml deleted file mode 100644 index b228d59..0000000 --- a/github-actions-iam-user.yml +++ /dev/null @@ -1,93 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Description: >- - Creates an IAM User, Policy, and Access Key for GitHub Actions to deploy AWS CDK stacks. - WARNING: Outputs AccessKeyId and SecretAccessKey. Secure these credentials immediately - and consider more secure authentication methods like OIDC. - -Parameters: - GitHubDeployUserName: - Type: String - Default: GitHubActionsDeployUser - Description: Name for the IAM user. - -Resources: - GitHubActionsUser: - Type: AWS::IAM::User - Properties: - UserName: !Ref GitHubDeployUserName - Policies: - - PolicyName: GitHubActionsDeployPolicy - PolicyDocument: - Version: '2012-10-17' - Statement: - - Effect: Allow # Permissions for CDK Toolkit and CloudFormation - Action: - - cloudformation:* - - s3:GetBucketLocation # Required by CDK for S3 assets - - s3:ListAllMyBuckets # Required by CDK for some operations - - ssm:GetParameter # For CDK context lookups from SSM - - iam:GetUser # To check current user identity - - iam:ListAccountAliases # For display purposes in CDK - - sts:GetCallerIdentity # For display purposes in CDK - - ecr:DescribeRepositories # If using ECR assets with CDK - Resource: "*" - - Effect: Allow # Permissions for CDK Bootstrap resources - Action: - - s3:* - Resource: - - !Sub "arn:aws:s3:::cdk-*-assets-${AWS::AccountId}-${AWS::Region}" - - !Sub "arn:aws:s3:::cdk-*-assets-${AWS::AccountId}-${AWS::Region}/*" - - Effect: Allow # Permissions for IAM roles created/managed by CDK - Action: - - iam:GetRole - - iam:GetInstanceProfile - - iam:CreateRole - - iam:DeleteRole - - iam:PutRolePolicy - - iam:AttachRolePolicy - - iam:DetachRolePolicy - - iam:DeleteRolePolicy - - iam:PassRole - - iam:TagRole - - iam:ListAttachedRolePolicies - - iam:ListRolePolicies - - iam:ListRoleTags - Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/cdk-*" - - Effect: Allow # Permissions for application-specific resources (ClockWebsiteStack) - Action: - - s3:* - Resource: - - !Sub "arn:aws:s3:::simple-clock-website-*-${AWS::AccountId}-${AWS::Region}" - - !Sub "arn:aws:s3:::simple-clock-website-*-${AWS::AccountId}-${AWS::Region}/*" - - Effect: Allow - Action: - - cloudfront:* - - route53:* - - acm:* - - logs:CreateLogGroup # For Lambda@Edge if used by CloudFront - - logs:CreateLogStream - - logs:PutLogEvents - - iam:CreateServiceLinkedRole # For services like CloudFront, Route53, ACM, etc. - Resource: "*" # These services often require broad permissions or create resources with unpredictable names. - # For stricter security, scope these down if possible after initial deployment. - - GitHubActionsUserAccessKey: - Type: AWS::IAM::AccessKey - Properties: - UserName: !Ref GitHubActionsUser - # WARNING: The SecretAccessKey will be visible in the AWS CloudFormation console - # and in API calls like DescribeStacks. Secure it immediately after creation. - -Outputs: - AccessKeyId: - Description: Access Key ID for the GitHub Actions IAM user. - Value: !Ref GitHubActionsUserAccessKey - SecretAccessKey: - Description: >- - Secret Access Key for the GitHub Actions IAM user. - IMPORTANT: Store this securely in GitHub Secrets and then consider removing this output - or the AccessKey resource from the template for enhanced security. - Value: !GetAtt GitHubActionsUserAccessKey.SecretAccessKey - IAMUserArn: - Description: ARN of the created IAM user. - Value: !GetAtt GitHubActionsUser.Arn diff --git a/iam-policy.json b/iam-policy.json deleted file mode 100644 index 1282686..0000000 --- a/iam-policy.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "cloudformation:CreateStack", - "cloudformation:UpdateStack", - "cloudformation:DeleteStack", - "cloudformation:DescribeStacks", - "cloudformation:DescribeStackEvents", - "cloudformation:DescribeStackResources", - "cloudformation:GetTemplate", - "cloudformation:ValidateTemplate", - "cloudformation:ListStacks", - "cloudformation:ListStackResources" - ], - "Resource": "*" - }, - { - "Effect": "Allow", - "Action": [ - "s3:CreateBucket", - "s3:DeleteBucket", - "s3:PutBucketWebsite", - "s3:PutBucketPublicAccessBlock", - "s3:PutBucketPolicy", - "s3:PutObject", - "s3:DeleteObject", - "s3:ListBucket", - "s3:GetBucketLocation", - "s3:GetBucketAcl", - "s3:GetObject" - ], - "Resource": [ - "arn:aws:s3:::cdk-*-assets-*-*", - "arn:aws:s3:::clockwebsitestack-*" - ] - }, - { - "Effect": "Allow", - "Action": [ - "iam:GetRole", - "iam:CreateRole", - "iam:DeleteRole", - "iam:PutRolePolicy", - "iam:AttachRolePolicy", - "iam:DetachRolePolicy", - "iam:PassRole" - ], - "Resource": "arn:aws:iam::*:role/cdk-*" - }, - { - "Effect": "Allow", - "Action": "sts:AssumeRole", - "Resource": "arn:aws:iam::*:role/cdk-*", - "Condition": { - "StringEquals": { - "iam:PassedToService": "cloudformation.amazonaws.com" - } - } - } - ] -}