Skip to content

Commit dd7bd0e

Browse files
committed
initial commit
0 parents  commit dd7bd0e

File tree

6 files changed

+390
-0
lines changed

6 files changed

+390
-0
lines changed

.gitignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Local .terraform directories
2+
**/.terraform/*
3+
4+
# .tfstate files
5+
*.tfstate
6+
*.tfstate.*
7+
8+
# Crash log files
9+
crash.log
10+
crash.*.log
11+
12+
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
13+
# password, private keys, and other secrets. These should not be part of version
14+
# control as they are data points which are potentially sensitive and subject
15+
# to change depending on the environment.
16+
*.tfvars
17+
*.tfvars.json
18+
19+
# Ignore override files as they are usually used to override resources locally and so
20+
# are not checked in
21+
override.tf
22+
override.tf.json
23+
*_override.tf
24+
*_override.tf.json
25+
26+
# Ignore transient lock info files created by terraform apply
27+
.terraform.tfstate.lock.info
28+
29+
# Include override files you do wish to add to version control using negated pattern
30+
# !example_override.tf
31+
32+
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
33+
# example: *tfplan*
34+
35+
# Ignore CLI configuration files
36+
.terraformrc
37+
terraform.rc
38+
39+
# Ignore IDE
40+
.idea/

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Fingerprint
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
## How to Install
2+
3+
### Using a new CloudFront distribution
4+
5+
1. Create a new directory `mkdir fingerprint_integration` and go inside `cd fingerprint_integration`
6+
2. Create a file `touch fingerprint.tf` and add below content, do not forget to replace placeholders (`AGENT_DOWNLOAD_PATH_HERE`, `RESULT_PATH_HERE`, `PROXY_SECRET_HERE`):
7+
```terraform
8+
module "fingerprint_cloudfront_integration" {
9+
source = "[email protected]:necipallef/terraform-module-proxy-lambda.git/?ref=v0.7.1"
10+
11+
fpjs_agent_download_path = "AGENT_DOWNLOAD_PATH_HERE"
12+
fpjs_get_result_path = "RESULT_PATH_HERE"
13+
fpjs_shared_secret = "PROXY_SECRET_HERE"
14+
}
15+
```
16+
3. Create a file called `cloudfront_distribution.tf` and add below content (feel free to make any changes that makes sense for your setup):
17+
```terraform
18+
19+
resource "aws_cloudfront_distribution" "fpjs_cloudfront_distribution" {
20+
comment = "Fingerprint distribution (created via Terraform)"
21+
22+
origin {
23+
domain_name = module.fingerprint_cloudfront_integration.fpjs_origin_name
24+
origin_id = module.fingerprint_cloudfront_integration.fpjs_origin_id
25+
custom_origin_config {
26+
origin_protocol_policy = "https-only"
27+
http_port = 80
28+
https_port = 443
29+
origin_ssl_protocols = ["TLSv1.2"]
30+
}
31+
custom_header {
32+
name = "FPJS_SECRET_NAME"
33+
value = module.fingerprint_cloudfront_integration.fpjs_secret_manager_arn
34+
}
35+
}
36+
37+
enabled = true
38+
39+
http_version = "http1.1"
40+
41+
price_class = "PriceClass_100"
42+
43+
default_cache_behavior {
44+
allowed_methods = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"]
45+
cached_methods = ["GET", "HEAD"]
46+
cache_policy_id = module.fingerprint_cloudfront_integration.fpjs_cache_policy_id
47+
origin_request_policy_id = module.fingerprint_cloudfront_integration.fpjs_origin_request_policy_id
48+
target_origin_id = module.fingerprint_cloudfront_integration.fpjs_origin_id
49+
viewer_protocol_policy = "https-only"
50+
compress = true
51+
52+
lambda_function_association {
53+
event_type = "origin-request"
54+
lambda_arn = module.fingerprint_cloudfront_integration.fpjs_proxy_lambda_arn
55+
include_body = true
56+
}
57+
}
58+
59+
viewer_certificate {
60+
cloudfront_default_certificate = true
61+
}
62+
63+
restrictions {
64+
geo_restriction {
65+
restriction_type = "none"
66+
}
67+
}
68+
}
69+
```
70+
If you wish to connect a custom domain for first-party benefits, consider changing `viewer_certificate` field accordingly. Refer to [official documentation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution) by HashiCorp for further customization.
71+
4. Run `terraform init`
72+
5. Run `terraform plan`, if all looks good run `terraform apply`
73+
74+
### Using existing CloudFront distribution
75+
76+
1. Create a file called `fingerprint.tf` and add below content, do not forget to replace placeholders (`AGENT_DOWNLOAD_PATH_HERE`, `RESULT_PATH_HERE`, `PROXY_SECRET_HERE`):
77+
```terraform
78+
module "fingerprint_cloudfront_integration" {
79+
source = "[email protected]:necipallef/terraform-module-proxy-lambda.git/?ref=v0.7.1"
80+
81+
fpjs_agent_download_path = "AGENT_DOWNLOAD_PATH_HERE"
82+
fpjs_get_result_path = "RESULT_PATH_HERE"
83+
fpjs_shared_secret = "PROXY_SECRET_HERE"
84+
}
85+
```
86+
2. Go to your CloudFront distribution block and add below content, do not forget to replace placeholders (`YOUR_INTEGRATION_PATH_HERE`):
87+
```terraform
88+
resource "aws_cloudfront_distribution" "cloudfront_dist" {
89+
// more code here
90+
91+
#region fingerprint start
92+
93+
origin {
94+
domain_name = module.fingerprint_cloudfront_integration.fpjs_origin_name
95+
origin_id = module.fingerprint_cloudfront_integration.fpjs_origin_id
96+
custom_origin_config {
97+
origin_protocol_policy = "https-only"
98+
http_port = 80
99+
https_port = 443
100+
origin_ssl_protocols = ["TLSv1.2"]
101+
}
102+
custom_header {
103+
name = "FPJS_SECRET_NAME"
104+
value = module.fingerprint_cloudfront_integration.fpjs_secret_manager_arn
105+
}
106+
}
107+
108+
ordered_cache_behavior {
109+
path_pattern = "YOUR_INTEGRATION_PATH_HERE/*"
110+
111+
allowed_methods = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"]
112+
cached_methods = ["GET", "HEAD"]
113+
cache_policy_id = module.fingerprint_cloudfront_integration.fpjs_cache_policy_id
114+
origin_request_policy_id = module.fingerprint_cloudfront_integration.fpjs_origin_request_policy_id
115+
target_origin_id = module.fingerprint_cloudfront_integration.fpjs_origin_id
116+
viewer_protocol_policy = "https-only"
117+
compress = true
118+
119+
lambda_function_association {
120+
event_type = "origin-request"
121+
lambda_arn = module.fingerprint_cloudfront_integration.fpjs_proxy_lambda_arn
122+
include_body = true
123+
}
124+
}
125+
126+
#endregion
127+
128+
// more code here
129+
}
130+
```
131+
3. Run `terraform plan`, if all looks good run `terraform apply`
132+
133+
> [!NOTE]
134+
> If your project doesn't use `hashicorp/random` module, then you will need to run `terraform init -upgrade`.
135+
136+
## Todo
137+
- [ ] create a public repo on company account with name `terraform-aws-fingerprint-cloudfront-integration`
138+
- [ ] publish on Hashicorp account

main.tf

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
terraform {
2+
required_providers {
3+
aws = {
4+
source = "hashicorp/aws"
5+
version = "~> 5.57.0"
6+
}
7+
random = {
8+
source = "hashicorp/random"
9+
version = "~> 3.6.2"
10+
}
11+
}
12+
}
13+
14+
resource "random_id" "integration_id" {
15+
byte_length = 6
16+
}
17+
18+
locals {
19+
integration_id = random_id.integration_id.hex
20+
}
21+
22+
# region cache policy
23+
24+
resource "aws_cloudfront_cache_policy" "fpjs_procdn" {
25+
name = "FingerprintProCDNCachePolicy-${local.integration_id}"
26+
default_ttl = 180
27+
max_ttl = 180
28+
min_ttl = 0
29+
30+
parameters_in_cache_key_and_forwarded_to_origin {
31+
cookies_config {
32+
cookie_behavior = "none"
33+
}
34+
35+
headers_config {
36+
header_behavior = "none"
37+
}
38+
39+
query_strings_config {
40+
query_string_behavior = "whitelist"
41+
query_strings {
42+
items = ["version", "loaderVersion"]
43+
}
44+
}
45+
46+
enable_accept_encoding_brotli = true
47+
enable_accept_encoding_gzip = true
48+
}
49+
}
50+
51+
# endregion
52+
53+
# region proxy lambda
54+
55+
data "aws_iam_policy_document" "assume_role" {
56+
statement {
57+
effect = "Allow"
58+
sid = "AllowAwsToAssumeRole"
59+
60+
principals {
61+
type = "Service"
62+
identifiers = ["lambda.amazonaws.com", "edgelambda.amazonaws.com"]
63+
}
64+
65+
actions = ["sts:AssumeRole"]
66+
}
67+
}
68+
69+
resource "aws_iam_role_policy" "fpjs_proxy_lambda" {
70+
name = "AWSSecretAccess"
71+
role = aws_iam_role.fpjs_proxy_lambda.id
72+
73+
policy = jsonencode({
74+
Version = "2012-10-17"
75+
Statement = [
76+
{
77+
Action = [
78+
"secretsmanager:GetSecretValue",
79+
]
80+
Effect = "Allow"
81+
Resource = aws_secretsmanager_secret.fpjs_proxy_lambda_secret.arn
82+
},
83+
]
84+
})
85+
}
86+
87+
resource "aws_iam_role" "fpjs_proxy_lambda" {
88+
name = "fingerprint-pro-lambda-role-${local.integration_id}"
89+
assume_role_policy = data.aws_iam_policy_document.assume_role.json
90+
}
91+
92+
data "aws_s3_object" "fpjs_integration_s3_bucket" {
93+
bucket = "fingerprint-pro-cloudfront-integration"
94+
key = "v2/lambda_latest.zip"
95+
}
96+
97+
resource "aws_lambda_function" "fpjs_proxy_lambda" {
98+
s3_bucket = data.aws_s3_object.fpjs_integration_s3_bucket.bucket
99+
s3_key = data.aws_s3_object.fpjs_integration_s3_bucket.key
100+
function_name = "fingerprint-pro-cloudfront-lambda-${local.integration_id}"
101+
role = aws_iam_role.fpjs_proxy_lambda.arn
102+
handler = "fingerprintjs-pro-cloudfront-lambda-function.handler"
103+
source_code_hash = data.aws_s3_object.fpjs_integration_s3_bucket.etag
104+
105+
runtime = "nodejs20.x"
106+
107+
publish = true
108+
}
109+
110+
# endregion
111+
112+
# region secrets manager
113+
114+
resource "aws_secretsmanager_secret" "fpjs_proxy_lambda_secret" {
115+
name = "fingerprint-pro-cloudfront-integration-settings-secret-${local.integration_id}"
116+
description = "AWS Secret with a custom Fingerprint integration settings (created via Terraform)"
117+
}
118+
119+
resource "aws_secretsmanager_secret_version" "fpjs_proxy_lambda_secret" {
120+
secret_id = aws_secretsmanager_secret.fpjs_proxy_lambda_secret.id
121+
secret_string = jsonencode(
122+
{
123+
fpjs_get_result_path = var.fpjs_get_result_path
124+
fpjs_agent_download_path = var.fpjs_agent_download_path
125+
fpjs_pre_shared_secret = var.fpjs_shared_secret
126+
}
127+
)
128+
}
129+
130+
# endregion

outputs.tf

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
output "fpjs_cache_policy_id" {
2+
value = aws_cloudfront_cache_policy.fpjs_procdn.id
3+
description = "Fingerprint integration cache policy id"
4+
}
5+
6+
output "fpjs_proxy_lambda_arn" {
7+
value = aws_lambda_function.fpjs_proxy_lambda.qualified_arn
8+
description = "Fingerprint integration proxy lambda ARN"
9+
}
10+
11+
output "fpjs_secret_manager_arn" {
12+
value = aws_secretsmanager_secret.fpjs_proxy_lambda_secret.arn
13+
description = "Fingerprint secrets integration manager secret ARN"
14+
}
15+
16+
# constants
17+
18+
output "fpjs_origin_name" {
19+
value = "fpcdn.io"
20+
description = "Fingerprint Pro CDN origin domain name"
21+
}
22+
23+
output "fpjs_origin_id" {
24+
value = "fpcdn.io"
25+
description = "Fingerprint Pro CDN origin domain id"
26+
}
27+
28+
output "fpjs_origin_request_policy_id" {
29+
value = "216adef6-5c7f-47e4-b989-5492eafa07d3" # Default AllViewer policy
30+
description = "Fingerprint Pro CDN origin request policy id"
31+
}

variables.tf

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
variable "fpjs_get_result_path" {
2+
type = string
3+
description = "request path used to send identification requests (aka FPJS_GET_RESULT_PATH)"
4+
5+
validation {
6+
condition = can(regex("^([a-zA-Z0-9\\-])+$", var.fpjs_get_result_path))
7+
error_message = "value should only consist of alphanumeric values and dashes"
8+
}
9+
}
10+
11+
variable "fpjs_agent_download_path" {
12+
type = string
13+
description = "request path used to send ProCDN requests (aka FPJS_AGENT_DOWNLOAD_PATH)"
14+
15+
validation {
16+
condition = can(regex("^([a-zA-Z0-9\\-])+$", var.fpjs_agent_download_path))
17+
error_message = "value should only consist of alphanumeric values and dashes"
18+
}
19+
}
20+
21+
variable "fpjs_shared_secret" {
22+
type = string
23+
sensitive = true
24+
description = "shared secret created on the Fingerprint dashboard (aka FPJS_PRE_SHARED_SECRET)"
25+
26+
validation {
27+
condition = can(regex("^([a-zA-Z0-9\\-])+$", var.fpjs_shared_secret))
28+
error_message = "value should only consist of alphanumeric values and dashes"
29+
}
30+
}

0 commit comments

Comments
 (0)