/// <summary> /// Used to modify cloudformation cross account artifacts to bucket owner full access. /// </summary> /// <param name="jobEvent">CodePipeline event.</param> /// <param name="context">Lambda Context</param> /// <returns>Job success of the Lambda</returns> public async Task <AmazonWebServiceResponse> FixCloudFormationOutputArtifactAcl(CodePipelineJobEvent jobEvent, ILambdaContext context) { var jobId = jobEvent.CodePipelineJob.Id; context.Logger.LogLine($"JobId: {jobId}"); using (var codePipelineClient = new AmazonCodePipelineClient()) using (var stsClient = new AmazonSecurityTokenServiceClient()) { try { var jobData = jobEvent.CodePipelineJob.Data; // Assume the role in the cloudformation account that screwed up the bucket permissions // for the output object var userParameters = jobData.ActionConfiguration.Configuration["UserParameters"]; var paramDict = JsonConvert.DeserializeObject <Dictionary <string, string> >(userParameters); var roleArn = paramDict["RoleArn"]; var assumeRoleRequest = new AssumeRoleRequest { RoleArn = roleArn, RoleSessionName = "codepipeline", DurationSeconds = 900 }; var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest); // Setup an S3 Client with the sts creds var s3Client = new AmazonS3Client(assumeRoleResponse.Credentials); // Update the ACLs of the input artifacts foreach (var inputArtifact in jobData.InputArtifacts) { var bucketName = inputArtifact.Location.S3Location.BucketName; var bucketKey = inputArtifact.Location.S3Location.ObjectKey; context.Logger.LogLine($"Fixing {bucketName}/{bucketKey}"); var putObjectAclRequest = new PutACLRequest { BucketName = bucketName, CannedACL = S3CannedACL.BucketOwnerFullControl, Key = bucketKey }; await s3Client.PutACLAsync(putObjectAclRequest); } // Send the success response var successResultRequest = new PutJobSuccessResultRequest { JobId = jobId }; return(await codePipelineClient.PutJobSuccessResultAsync(successResultRequest)); } catch (Exception ex) { // Send the failure response and log return(await DoException(codePipelineClient, ex, jobId, context)); } } }
/// <summary> /// Used to modify recordset with value from api gateway code deploy in another account. /// </summary> /// <param name="jobEvent">CodePipeline event.</param> /// <param name="context">Lambda Context</param> /// <returns>Job success of the Lambda</returns> public async Task <AmazonWebServiceResponse> UpdateApiGatewayAliasRecordSet(CodePipelineJobEvent jobEvent, ILambdaContext context) { var jobId = jobEvent.CodePipelineJob.Id; context.Logger.LogLine($"JobId: {jobId}"); using (var codePipelineClient = new AmazonCodePipelineClient()) using (var s3Client = new AmazonS3Client()) using (var dnsClient = new AmazonRoute53Client()) { // Prep the user parameters var userParameters = jobEvent.CodePipelineJob.Data.ActionConfiguration.Configuration["UserParameters"]; context.Logger.LogLine("UserParameters:"); context.Logger.LogLine(userParameters); var paramDict = JsonConvert.DeserializeObject <Dictionary <string, string> >(userParameters); try { DnsSettings dnsSettings = null; // Get the first (only) input artifact var artifact = jobEvent.CodePipelineJob.Data.InputArtifacts.First(); var artifactBucketName = artifact.Location.S3Location.BucketName; var artifactBucketKey = artifact.Location.S3Location.ObjectKey; // Unzip and get json using (var getResponse = await s3Client.GetObjectAsync(artifactBucketName, artifactBucketKey)) { var memoryStream = new MemoryStream(); using (var objectStream = getResponse.ResponseStream) { objectStream.CopyTo(memoryStream); } var searchFile = paramDict["DnsJson"]; context.Logger.LogLine("Unziping artifact"); context.Logger.LogLine($"Searching for {searchFile}"); using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Read)) { foreach (var entry in archive.Entries) { var fileName = entry.Name; context.Logger.LogLine("Checking File: " + entry.Name); if (searchFile == fileName) { using (var fileStream = entry.Open()) using (var streamReader = new StreamReader(fileStream)) { var dnsJson = await streamReader.ReadToEndAsync(); dnsSettings = JsonConvert.DeserializeObject <DnsSettings>(dnsJson); } break; } } } } // Get the hosted zones in the tools region context.Logger.LogLine($"Searching for {dnsSettings.HostedZoneLookupDomainName}"); var hostedZones = await dnsClient.ListHostedZonesAsync(); var myHostedZone = hostedZones.HostedZones.FirstOrDefault(z => z.Name == dnsSettings.HostedZoneLookupDomainName); if (myHostedZone == null) { var noZoneMessage = $"Hosted Zone {dnsSettings.HostedZoneLookupDomainName} could not be found"; context.Logger.LogLine(noZoneMessage); var failureDetails = new FailureDetails { Message = noZoneMessage, Type = FailureType.ConfigurationError }; return(await codePipelineClient.PutJobFailureResultAsync(jobId, failureDetails)); } // The record set we need to create var recordSet = new ResourceRecordSet { Name = dnsSettings.WebApiDnsDomain, Type = RRType.A, ResourceRecords = new List <ResourceRecord> { new ResourceRecord { Value = $"ALIAS {dnsSettings.RegionalDomainName}" } } }; var rsChange = new Change { Action = ChangeAction.UPSERT, ResourceRecordSet = recordSet }; var rsChangeBatch = new ChangeBatch { Changes = new List <Change> { rsChange } }; // Create/Update the recordset var changeDnsRequest = new ChangeResourceRecordSetsRequest { ChangeBatch = rsChangeBatch, HostedZoneId = myHostedZone.Id }; var changeResponse = await dnsClient.ChangeResourceRecordSetsAsync(changeDnsRequest); // Log and send the success response context.Logger.LogLine($"Request Id {changeResponse.ChangeInfo.Id} submitted"); context.Logger.LogLine($"{dnsSettings.WebApiDnsDomain} => A ALIAS {dnsSettings.RegionalDomainName}"); var successResultRequest = new PutJobSuccessResultRequest { JobId = jobId }; return(await codePipelineClient.PutJobSuccessResultAsync(successResultRequest)); } catch (Exception ex) { // Send the failure response and log return(await DoException(codePipelineClient, ex, jobId, context)); } } }