0

I have created a simple stack to deploy with cdk using typescript. These are my dependencies:

    {
  "name": "ec2-cdk",
  "version": "0.1.0",
  "bin": {
    "ec2-cdk": "bin/ec2-cdk.js"
  },
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "cdk": "cdk"
  },
  "devDependencies": {
    "@types/jest": "^29.5.3",
    "@types/node": "20.4.9",
    "jest": "^29.6.2",
    "ts-jest": "^29.1.1",
    "aws-cdk": "2.91.0",
    "ts-node": "^10.9.1",
    "typescript": "~5.1.6"
  },
  "dependencies": {
    "aws-cdk-lib": "2.91.0",
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.21"
  }
}

I have setup github token - personal token and saved it in secrets manager. In my code I point that to retrieve it from secrets manager. It is retrieving and I get below error when doing code deploy

| CREATE_FAILED | AWS::CodePipeline::Pipeline | pythonwebpipeline3CD50BBE The OAuth token used for the GitHub source action GithubSource exceeds the maximum allowed length of 100 characters. (Service: AWSCodePipeline; Sta tus Code: 400; Error Code: InvalidActionDeclarationException; Request ID: 87a8da36-b4fa-4dec-966a-be29ac35b263; Proxy: null)

Thanks

code here:

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
// import * as sqs from 'aws-cdk-lib/aws-sqs';
import { readFileSync } from 'fs';
import { Vpc, SubnetType, Peer, Port, AmazonLinuxGeneration, 
  AmazonLinuxCpuType, Instance, SecurityGroup, AmazonLinuxImage,
  InstanceClass, InstanceSize, InstanceType
} from 'aws-cdk-lib/aws-ec2';
import { Role, ServicePrincipal, ManagedPolicy } from 'aws-cdk-lib/aws-iam';
import { Pipeline, Artifact } from 'aws-cdk-lib/aws-codepipeline';
import { GitHubSourceAction, CodeBuildAction, CodeDeployServerDeployAction } from 'aws-cdk-lib/aws-codepipeline-actions';
import { PipelineProject, LinuxBuildImage } from 'aws-cdk-lib/aws-codebuild';
import { ServerDeploymentGroup, ServerApplication, InstanceTagSet } from 'aws-cdk-lib/aws-codedeploy';
import { SecretValue } from 'aws-cdk-lib';



export class PythonEc2BlogpostStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    // example resource
    // const queue = new sqs.Queue(this, 'Ec2CdkQueue', {
    //   visibilityTimeout: cdk.Duration.seconds(300)
    // });

    const webServerRole = new Role(this, "ec2Role", {
      assumedBy: new ServicePrincipal("ec2.amazonaws.com"),
    });

    // IAM policy attachment to allow access to
    webServerRole.addManagedPolicy(
      ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore")
    );

    webServerRole.addManagedPolicy(
      ManagedPolicy.fromAwsManagedPolicyName("service-role/AmazonEC2RoleforAWSCodeDeploy")
    );

    // This VPC has 3 public subnets, and that's it
    const vpc = new Vpc(this, 'main_vpc',{
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: 'pub01',
          subnetType: SubnetType.PUBLIC,
        },
        {
          cidrMask: 24,
          name: 'pub02',
          subnetType: SubnetType.PUBLIC,
        },
        {
          cidrMask: 24,
          name: 'pub03',
          subnetType: SubnetType.PUBLIC,
        }
      ]
    });

    // Security Groups
    // This SG will only allow HTTP traffic to the Web server
    const webSg = new SecurityGroup(this, 'web_sg',{
      vpc,
      description: "Allows Inbound HTTP traffic to the web server.",
      allowAllOutbound: true,
    });

    webSg.addIngressRule(
      Peer.anyIpv4(),
      Port.tcp(80)
    );

    // the AMI to be used for the EC2 Instance
    const ami = new AmazonLinuxImage({
      generation: AmazonLinuxGeneration.AMAZON_LINUX_2,
      cpuType: AmazonLinuxCpuType.X86_64,
    });

    // The actual Web EC2 Instance for the web server
    const webServer = new Instance(this, 'web_server',{
      vpc,
      instanceType: InstanceType.of(
        InstanceClass.T2,
        InstanceSize.MICRO,
      ),
      machineImage: ami,
      securityGroup: webSg,
      role: webServerRole,
    });

    // User data - used for bootstrapping
    const webSGUserData = readFileSync('./assets/configure_amz_linux_sample_app.sh','utf-8');
    webServer.addUserData(webSGUserData);
    // Tag the instance
    cdk.Tags.of(webServer).add('application-name','python-web')
    cdk.Tags.of(webServer).add('stage','prod')
    

    // CodePipeline
    const pipeline = new Pipeline(this, 'python_web_pipeline',{
      pipelineName: 'python-webApp',
      crossAccountKeys: false, // solves the encrypted bucket issue
    });

    // STAGES
    // Source Stage
    const sourceStage = pipeline.addStage({
      stageName: 'Source',
    })
    
    // Build Stage
    const buildStage = pipeline.addStage({
      stageName: 'Build',
    })
    
    // Deploy Stage
    const deployStage = pipeline.addStage({
      stageName: 'Deploy',
    })

    // Source action
    const sourceOutput = new Artifact();
    const githubSourceAction = new GitHubSourceAction({
      actionName: 'GithubSource',
      oauthToken: SecretValue.secretsManager('github-oauth-token-1'), // MAKE SURE TO SET UP BEFORE
      owner: 'AmitKulkarni9', // THIS NEEDS TO BE CHANGED TO YOUR OWN USER ID
      repo: 'sample-python-web-app',
      branch: 'main',
      output: sourceOutput,
    });

    sourceStage.addAction(githubSourceAction);

    // Build Action
    const pythonTestProject = new PipelineProject(this, 'pythonTestProject',{
      environment: {
        buildImage: LinuxBuildImage.AMAZON_LINUX_2_3
      }
    });

    const pythonTestOutput = new Artifact();

    const pythonTestAction = new CodeBuildAction({
      actionName: 'TestPython',
      project: pythonTestProject,
      input: sourceOutput,
      outputs: [pythonTestOutput]
    });

    buildStage.addAction(pythonTestAction);

    // Deploy Actions
    const pythonDeployApplication = new ServerApplication(this,"python_deploy_application",{
      applicationName: 'python-webApp'
    });

    // Deployment group
    const pythonServerDeploymentGroup = new ServerDeploymentGroup(this,'PythonAppDeployGroup',{
      application: pythonDeployApplication,
      deploymentGroupName: 'PythonAppDeploymentGroup',
      installAgent: true,
      ec2InstanceTags: new InstanceTagSet(
      {
        'application-name': ['python-web'],
        'stage':['prod', 'stage']
      })
    });

    // Deployment action
    const pythonDeployAction = new CodeDeployServerDeployAction({
      actionName: 'PythonAppDeployment',
      input: sourceOutput,
      deploymentGroup: pythonServerDeploymentGroup,
    });

    deployStage.addAction(pythonDeployAction);

    // Output the public IP address of the EC2 instance
    new cdk.CfnOutput(this, "IP Address", {
      value: webServer.instancePublicIp,
    });    
    

    

  }
}

gshpychka
  • 8,523
  • 1
  • 11
  • 31
  • Add your CDK code as well. – gshpychka Aug 12 '23 at 13:57
  • @gshpychka added code – Amit Kulkarni Aug 12 '23 at 16:40
  • Okay, obvious question - how long is your secret? Is it just the token or did you wrap it in some json? – gshpychka Aug 14 '23 at 06:40
  • Just a Token. No Expiration – Amit Kulkarni Aug 14 '23 at 14:32
  • I guess you need to actually retrieve the secret value with AWS SDK and see how many characters are returned. – gshpychka Aug 14 '23 at 19:01
  • console.log shows ``` SecretValue { creationStack: [ 'stack traces disabled' ], value: CfnDynamicReference { creationStack: [ 'stack traces disabled' ], value: '{{resolve:secretsmanager:github-oauth-token-1:SecretString:::}}', typeHint: 'string' }, typeHint: 'string', rawValue: CfnDynamicReference { creationStack: [ 'stack traces disabled' ], value: '{{resolve:secretsmanager:github-oauth-token-1:SecretString:::}}', typeHint: 'string' } } ``` – Amit Kulkarni Aug 16 '23 at 13:38
  • That will be resolved during cdk syth and I checked the json in s3 bucket which is correct "OAuthToken": "{{resolve:secretsmanager:github-oauth-token-1:SecretString:::}}" – Amit Kulkarni Aug 16 '23 at 13:43
  • 1
    Yes, I mentioned retrieving the secret with AWS SDK, not CDK. Get the actual value (not the reference) and see how many characters it is. – gshpychka Aug 16 '23 at 13:47
  • Solved :) InvalidRequestException: You can't perform this operation on the secret because it was marked for deletion. Created new secret and all working now. Thanks – Amit Kulkarni Aug 17 '23 at 14:58
  • Cool, make sure to add and accept an answer for others – gshpychka Aug 17 '23 at 15:19

1 Answers1

0

Use SDK to retrieve and check the secrets can be retrieved. retrieving the secret with AWS SDK will give you proper error message if something is wrong with it, like this: InvalidRequestException: You can't perform this operation on the secret because it was marked for deletion.

Confirm secret is retrieved and as per expected then it will work with cdk.