Skip to content

Instantly share code, notes, and snippets.

@thesurlydev
Last active June 19, 2019 17:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thesurlydev/b58a6618f6175e7e802f22b9a4977886 to your computer and use it in GitHub Desktop.
Save thesurlydev/b58a6618f6175e7e802f22b9a4977886 to your computer and use it in GitHub Desktop.
CodeBuild and GH webhook goodness
import com.amazonaws.services.lambda.runtime.Context
import com.seekret.arch.customresources.model.RequestBody
import org.kohsuke.github.GHEvent
import org.kohsuke.github.GitHub
import software.amazon.awssdk.services.codebuild.CodeBuildClient
import software.amazon.awssdk.services.codebuild.model.CreateWebhookRequest
import software.amazon.awssdk.services.codebuild.model.CreateWebhookResponse
import software.amazon.awssdk.services.codebuild.model.DeleteWebhookRequest
import software.amazon.awssdk.services.codebuild.model.ResourceAlreadyExistsException
import software.amazon.awssdk.services.codebuild.model.WebhookFilter
import software.amazon.awssdk.services.codebuild.model.WebhookFilterType
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest
import java.lang.IllegalStateException
@Suppress("unused")
class CodeBuildWebhookHandler : AbstractCustomResourceHandler() {
override fun doCreate(request: RequestBody, context: Context) {
val client = CodeBuildClient.create()
val projectName = request.tryGetStringProperty("ProjectName")
val webhookFilters = listOf(
WebhookFilter.builder().type(WebhookFilterType.EVENT).pattern("PUSH").build()
)
val createWebhookRequest = CreateWebhookRequest.builder()
.projectName(projectName)
.filterGroups(webhookFilters)
.build()
val createWebhookResponse: CreateWebhookResponse = try {
client.createWebhook(createWebhookRequest)
} catch (ae: ResourceAlreadyExistsException) {
return sendFailedResponse(request, context, "Webhook already exists!")
}
val successful = createWebhookResponse.sdkHttpResponse().isSuccessful
when {
successful -> {
// call GitHub to create webhook with payloadUrl and secret
val webhook = createWebhookResponse.webhook()
val hookPayloadUrl = webhook.payloadUrl()
val hookSecret = webhook.secret()
createHook(request, hookPayloadUrl, hookSecret)
sendSuccessResponse(request, context, "Created Webhook")
}
else -> sendFailedResponse(request, context, "Error creating Webhook")
}
}
override fun doDelete(request: RequestBody, context: Context) {
val projectName = request.resourceProperties["ProjectName"] as String
val deleteWebhookRequest = DeleteWebhookRequest.builder().projectName(projectName).build()
val deleteWebhookResponse = CodeBuildClient.create().deleteWebhook(deleteWebhookRequest)
if (deleteWebhookResponse.sdkHttpResponse().isSuccessful) {
sendSuccessResponse(request, context, "Deleted Webhook")
} else {
sendFailedResponse(request, context, "Error deleting Webhook")
}
}
override fun doUpdate(request: RequestBody, context: Context) {
sendSuccessResponse(request, context, "Not implemented")
}
private fun createHook(request: RequestBody, hookPayloadUrl: String, hookSecret: String) {
log("Creating webhook")
val gitHubUser = request.tryGetStringProperty("GitHubUser")
val gitHubRepo = request.tryGetStringProperty("GitHubRepo")
val gitHubPersonalAccessTokenSecretId = request.tryGetStringProperty("GitHubPersonalAccessTokenSecretId")
val gitHubEndpoint = request.tryGetStringProperty("GitHubEndpoint")
// get GitHub personal access token from Secrets Manager
val sm = SecretsManagerClient.create()
val getSecretValueRequest = GetSecretValueRequest.builder().secretId(gitHubPersonalAccessTokenSecretId).build()
val getSecretValueResponse = sm.getSecretValue(getSecretValueRequest)
val sdkHttpResponse = getSecretValueResponse.sdkHttpResponse()
val gitHubPersonalAccessToken = if (sdkHttpResponse.isSuccessful) {
getSecretValueResponse.secretString()
} else {
throw IllegalStateException("Error getting GitHub personal access token from secretId: $gitHubPersonalAccessTokenSecretId; ${sdkHttpResponse.statusText()}")
}
log("Successfully retrieved GH personal access token")
val gh: GitHub = GitHub.connectToEnterpriseWithOAuth(gitHubEndpoint, gitHubUser, gitHubPersonalAccessToken)
val repo = gh.myself.getRepository(gitHubRepo)
val conf = mapOf(
"url" to hookPayloadUrl,
"content_type" to "json",
"secret" to hookSecret
)
val events = listOf(GHEvent.PUSH)
repo.createHook("web", conf, events, true)
log("Webhook creation successful")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment