Skip to content

Commit

Permalink
fix: Various code refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
robh007 committed Apr 13, 2023
1 parent 6e287b7 commit 9f4985e
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 114 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
**/.terraform/*
**.terraform.lock.hcl
**/builds/*

.infracost
# .tfstate files
*.tfstate
*.tfstate.*
Expand Down
37 changes: 17 additions & 20 deletions examples/aws-ecs/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,52 +16,49 @@ terraform {
module "ecs_cluster" {
source = "../../"

aws_request_config = {
ecs_cluster = {
lambda_function_name = "aws-lambda-signer"

aws_request_config = [
{
name = "ecs-cluster"
service = "ecs"
region = "eu-west-1"
url = "https://ecs.eu-west-1.amazonaws.com"
create = {
mode = "create"
service = "ecs"
region = "eu-west-1"
method = "POST"
url = "https://ecs.eu-west-1.amazonaws.com"
response_codes = [200, 400, 403]
method = "POST"
headers = {
Accept-Encoding = "identity"
Content-Type = "application/x-amz-json-1.1"
X-Amz-Target = "AmazonEC2ContainerServiceV20141113.CreateCluster"
}
data = {
"clusterName" = "RobsClusterAPI"
"clusterName" = "RobsClusterAPI-v2"
}
params = {
"Action" = "CreateCluster"
}
}
destroy = {
mode = "destroy"
service = "ecs"
region = "eu-west-1"
method = "POST"
url = "https://ecs.eu-west-1.amazonaws.com"
response_codes = [200, 400, 403]
method = "POST"
headers = {
Accept-Encoding = "identity"
Content-Type = "application/x-amz-json-1.1"
X-Amz-Target = "AmazonEC2ContainerServiceV20141113.DeleteCluster"
}
data = {
"cluster" = "RobsClusterAPI"
"cluster" = "RobsClusterAPI-v2"
}
params = {
"Action" = "DeleteCluster"
}
}
}
}
]
}

output "http_response" {
value = module.ecs_cluster.response
}

output "http_status" {
value = module.ecs_cluster.status_code
output "request" {
value = module.ecs_cluster
}
78 changes: 43 additions & 35 deletions examples/aws-iam/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,71 +5,83 @@ provider "aws" {
provider "terracurl" {
}

terraform {
required_providers {
terracurl = {
source = "devops-rob/terracurl"
}
}
}

module "iam_group" {
source = "../../"

awsaws_request_config = {
terraform_group = {
aws_request_config = [
{
name = "TerraformGroup"
service = "iam"
region = "us-east-1"
method = "POST"
url = "https://iam.amazonaws.com"
create = {
mode = "create"
service = "iam"
region = "us-east-1"
method = "POST"
url = "https://iam.amazonaws.com"
headers = {}
data = {}
response_codes = [200, 403, 404]
method = "POST"
headers = {
Content-Type = "application/x-amz-json-1.1"
}
data = {}
params = {
Action = "CreateGroup",
GroupName = "TerraformGroup",
Version = "2010-05-08"

}
}
destroy = {
mode = "destroy"
service = "iam"
region = "us-east-1"
method = "POST"
url = "https://iam.amazonaws.com"
headers = {}
data = {}
data = {
Content-Type = "application/x-amz-json-1.1"
}
params = {
Action = "DeleteGroup",
GroupName = "TerraformGroup",
Version = "2010-05-08"
}
}
}
ecs_group = {
},
{
name = "ecs_group"
service = "iam"
region = "us-east-1"
url = "https://iam.amazonaws.com"
create = {
mode = "create"
service = "iam"
region = "us-east-1"
method = "POST"
url = "https://iam.amazonaws.com"
headers = {}
data = {}
method = "POST"
response_codes = [200, 403, 404]
headers = {
Content-Type = "application/x-amz-json-1.1"
}
data = {}
params = {
Action = "CreateGroup",
GroupName = "ECSGroup",
Version = "2010-05-08"
}
}
destroy = {
mode = "destroy"
service = "iam"
region = "us-east-1"
method = "POST"
url = "https://iam.amazonaws.com"
headers = {}
data = {}
method = "POST"
headers = {
Content-Type = "application/x-amz-json-1.1"
}
data = {}
params = {
Action = "DeleteGroup",
GroupName = "ECSGroup",
Version = "2010-05-08"
}
}
}
}
]
}

output "response" {
Expand All @@ -80,10 +92,6 @@ output "request_url" {
value = module.iam_group.request_url
}

output "signed_response" {
value = module.iam_group.sigv4_config
}

output "status_code" {
value = module.iam_group.status_code
}
69 changes: 33 additions & 36 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ locals {
}

locals {
request_helper = flatten([
for req, config in local.config : [
for rt, d in config : {
name = "${req}_${d.mode}"
config = d
}
]
]
)
request_helper = { for k, config in local.config : config.name => {
config_create = {
config = config.create
url = config.url
service = config.service
region = config.region
}
config_destroy = {
config = config.destroy
url = config.url
service = config.service
region = config.region
} } }
}

// Generates a set of SIGV4 requests for create & destory methods request.
// Generates a set of SIGV4 requests for create & destory method requests.
data "aws_lambda_invocation" "sigv4" {
for_each = { for d in local.request_helper : d.name => d.config }
for_each = local.request_helper

function_name = var.lambda_function_name
input = jsonencode(each.value)
Expand All @@ -27,31 +31,24 @@ data "aws_lambda_invocation" "sigv4" {
// This is because the make up of the SIGV4 signature includes body & request parameters plus headers.
// So we use the response from the lambd invocation in the parts that require this.
resource "terracurl_request" "create_and_destroy" {
for_each = toset(keys(local.config))
for_each = local.request_helper

name = each.key
url = try(local.config[each.key]["create"]["url"], null)
method = try(local.config[each.key]["create"]["method"], null)

response_codes = [200, 400, 403]

headers = try(jsondecode(data.aws_lambda_invocation.sigv4["${each.key}_create"].result)["headers"], null)
request_body = try(jsondecode(data.aws_lambda_invocation.sigv4["${each.key}_create"].result)["data"], null)
request_parameters = try(jsondecode(data.aws_lambda_invocation.sigv4["${each.key}_create"].result)["request_params"], null)

destroy_url = try(local.config[each.key]["destroy"]["url"], null)
destroy_method = try(local.config[each.key]["destroy"]["method"], null)
destroy_headers = try(jsondecode(data.aws_lambda_invocation.sigv4["${each.key}_destroy"].result)["headers"], null)
destroy_request_body = try(jsondecode(data.aws_lambda_invocation.sigv4["${each.key}_destroy"].result)["data"], null)
destroy_parameters = try(jsondecode(data.aws_lambda_invocation.sigv4["${each.key}_destroy"].result)["request_params"], null)

destroy_response_codes = contains(keys(local.config[each.key]), "destroy") ? [200, 400, 403] : null

// This is just a create & destroy method, any modifications to the resource will result in a different API call.
// Which in turn results in a different SIGV4 authorization request. But terracurl only supports Create / Destroy.
// So this resource will ignore any changes, there's potential for a modification resource. But I suspect that may be get messy.
// Although if you control the ordering of the map sent in, you could modify the resource after Creation call.
lifecycle {
ignore_changes = all
}
url = try(local.request_helper[each.key].config_create["url"], null)
method = try(local.request_helper[each.key].config_create["config"]["method"], null)

response_codes = local.request_helper[each.key].config_create["config"]["response_codes"]

headers = try(jsondecode(data.aws_lambda_invocation.sigv4[each.key].result)["config_create"]["headers"], null)
request_body = try(jsondecode(data.aws_lambda_invocation.sigv4[each.key].result)["config_create"]["data"], null)
request_parameters = try(jsondecode(data.aws_lambda_invocation.sigv4[each.key].result)["config_create"]["request_params"], null)

destroy_url = try(local.request_helper[each.key].config_destroy["url"], null)
destroy_method = try(local.request_helper[each.key].config_destroy["config"]["method"], null)

destroy_headers = try(jsondecode(data.aws_lambda_invocation.sigv4[each.key].result)["config_destroy"]["headers"], null)
destroy_request_body = try(jsondecode(data.aws_lambda_invocation.sigv4[each.key].result)["config_destroy"]["data"], null)
destroy_parameters = try(jsondecode(data.aws_lambda_invocation.sigv4[each.key].result)["config_destroy"]["request_params"], null)

destroy_response_codes = try(local.request_helper[each.key].config_create["config"]["response_codes"], null)
}
28 changes: 23 additions & 5 deletions modules/sigv4-signer/src/lambda_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,35 @@


def lambda_handler(event, context):
return process_config(event)
sigv4_resp = {}

for lifecycle_event in event.keys():
print("Lifecycle event config")
print(event[lifecycle_event])

sigv4_resp.update(
{lifecycle_event: process_config(event[lifecycle_event])})

return sigv4_resp


def process_config(config):
if config.get('config') == None:
config_items = {}
else:
config_items = config.get('config')

# Remove any None elements in the config
config_items = {k: v for k, v in config_items.items() if v != None}

service = config.get('service', '')
url = config.get('url', '')
region = config.get('region', '')
method = config.get('method', '')
headers = config.get('headers', {})
params = config.get('params', {})
data = config.get('data', {})

method = config_items.get('method', '')
headers = config_items.get('headers', {})
params = config_items.get('params', {})
data = config_items.get('data', {})

request_config = {
'method': method.upper(),
Expand Down
8 changes: 0 additions & 8 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
output "local_config" {
value = local.config
}

output "sigv4_config" {
value = { for k, v in data.aws_lambda_invocation.sigv4 : k => v }
}

output "status_code" {
value = flatten([
for k, v in terracurl_request.create_and_destroy : [
Expand Down
31 changes: 22 additions & 9 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,27 @@ variable "lambda_function_name" {
}

variable "aws_request_config" {
description = "Map of request configuration, needs to contain create keys as a minimum. Destroy keys dont need to be included, however this will leave orphaned resources"
description = "List object with details of Configuration paramters"
default = []

type = map(any)

default = {
request_1 = {
create = {}
destroy = {}
}
}
type = list(object({
name = string
url = string
region = string
service = string
create = object({
response_codes = list(string)
method = optional(string)
headers = optional(map(string))
params = optional(map(string))
data = optional(map(string))
})
destroy = optional(object({
response_codes = optional(list(string))
method = optional(string)
headers = optional(map(string))
params = optional(map(string))
data = optional(map(string))
}))
}))
}

0 comments on commit 9f4985e

Please sign in to comment.