commit e9f9ba7084f0f716fbd7166f00e5090dfd8d378a Author: Michaela Date: Sat Jan 30 21:07:34 2021 +1000 initial diff --git a/README.md b/README.md new file mode 100644 index 0000000..4c3a85c --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +WIP +== +todo +-- + - Most of this was generated using former2, so it's very rough, need to rename things to make sense + - lambda layers should be scripted so we can deploy them again (or at the least documented), or move to packaging them into the deployable + - all the sondehub v1 stuff needs migrating, rebuilding + - web interface + - basic APIs + - build out APIs for sondehub ui replacement + - we don't have rate limiting ? do we need it + - cognito needs to be setup to allow private access + - replace profile defination with env variables since not all admins will have that profile + - \ No newline at end of file diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..3458297 --- /dev/null +++ b/main.tf @@ -0,0 +1,630 @@ +terraform { + backend "s3" { + bucket = "sondehub-terraform" + key = "sondehub-main" + region = "us-east-1" + profile = "sondes" + } +} +provider "aws" { + region = "us-east-1" + profile = "sondes" +} + +locals { + domain_name = "v2.sondehub.org" +} +data "aws_caller_identity" "current" {} + + +resource "aws_iam_role" "IAMRole" { + path = "/" + name = "Cognito_sondesAuth_Role" + assume_role_policy = < { + name = dvo.resource_record_name + record = dvo.resource_record_value + type = dvo.resource_record_type + } + } + + allow_overwrite = true + name = each.value.name + records = [each.value.record] + ttl = 60 + type = each.value.type + zone_id = aws_route53_zone.Route53HostedZone.zone_id +} +resource "aws_acm_certificate_validation" "CertificateManagerCertificate" { + certificate_arn = aws_acm_certificate.CertificateManagerCertificate.arn + validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn] +} + +resource "aws_route53_record" "Route53RecordSet5" { + name = "api" + type = "CNAME" + ttl = 60 + records = [ + "${aws_apigatewayv2_domain_name.ApiGatewayV2DomainName.domain_name_configuration.0.target_domain_name}." + ] + zone_id = aws_route53_zone.Route53HostedZone.zone_id +} + +resource "aws_cognito_user_pool_domain" "main" { + domain = "auth.${local.domain_name}" + user_pool_id = aws_cognito_user_pool.CognitoUserPool.id + certificate_arn = aws_acm_certificate_validation.CertificateManagerCertificate.certificate_arn +} + +resource "aws_route53_record" "Route53RecordSet6" { + name = "auth" + type = "A" + alias { + name = "${aws_cognito_user_pool_domain.main.cloudfront_distribution_arn}." + zone_id = "Z2FDTNDATAQYW2" + evaluate_target_health = false + } + zone_id = aws_route53_zone.Route53HostedZone.zone_id +} + +resource "aws_route53_record" "Route53RecordSet7" { + name = "es" + type = "CNAME" + ttl = 300 + records = [ + aws_elasticsearch_domain.ElasticsearchDomain.endpoint + ] + zone_id = aws_route53_zone.Route53HostedZone.zone_id +} + +data "archive_file" "api_to_iot" { + type = "zip" + source_file = "sonde-api-to-iot-core/lambda_function.py" + output_path = "${path.module}/build/sonde-api-to-iot-core.zip" +} + +resource "aws_lambda_function" "LambdaFunction" { + function_name = "sonde-api-to-iot-core" + handler = "lambda_function.lambda_handler" + filename = "${path.module}/build/sonde-api-to-iot-core.zip" + source_code_hash = data.archive_file.api_to_iot.output_base64sha256 + publish = true + memory_size = 256 + role = aws_iam_role.IAMRole5.arn + runtime = "python3.7" + timeout = 10 + tracing_config { + mode = "Active" + } + layers = [ + "arn:aws:lambda:us-east-1:${data.aws_caller_identity.current.account_id}:layer:xray-python:1", + "arn:aws:lambda:us-east-1:${data.aws_caller_identity.current.account_id}:layer:iot:3" + ] +} + +resource "aws_lambda_permission" "LambdaPermission2" { + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.LambdaFunction.arn + principal = "apigateway.amazonaws.com" + source_arn = "arn:aws:execute-api:us-east-1:${data.aws_caller_identity.current.account_id}:r03szwwq41/*/*/sondes/telemetry" +} + +resource "aws_lambda_layer_version" "LambdaLayerVersion2" { + compatible_runtimes = [ + "python3.8" + ] + layer_name = "iot" + s3_bucket = "sondehub-lambda-layers" + s3_key = "iot.zip" + source_code_hash = "sHyE9vXk+BzFphPe8evfiL79fcxsSEYVfpbTVi2IwH0=" +} + + +resource "aws_lambda_layer_version" "LambdaLayerVersion4" { + compatible_runtimes = [ + "python3.8" + ] + layer_name = "xray-python" + s3_bucket = "sondehub-lambda-layers" + s3_key = "xray-python.zip" + source_code_hash = "ta4o2brS2ZRAeWhZjqrm6MhOc3RlYNgkOuD4dxSonEc=" +} + +resource "aws_s3_bucket" "S3Bucket" { + bucket = "sondehub-lambda-layers" +} + +resource "aws_cloudwatch_log_group" "LogsLogGroup" { + name = "/aws/lambda/sonde-api-to-iot-core" +} + +resource "aws_apigatewayv2_api" "ApiGatewayV2Api" { + name = "sondehub-v2" + disable_execute_api_endpoint = true + api_key_selection_expression = "$request.header.x-api-key" + protocol_type = "HTTP" + route_selection_expression = "$request.method $request.path" +} + +resource "aws_apigatewayv2_stage" "ApiGatewayV2Stage" { + name = "$default" + api_id = aws_apigatewayv2_api.ApiGatewayV2Api.id + deployment_id = aws_apigatewayv2_deployment.ApiGatewayV2Deployment3.id + default_route_settings { + detailed_metrics_enabled = false + } + auto_deploy = true +} + +resource "aws_apigatewayv2_stage" "ApiGatewayV2Stage2" { + name = "prod" + api_id = aws_apigatewayv2_api.ApiGatewayV2Api.id + deployment_id = aws_apigatewayv2_deployment.ApiGatewayV2Deployment4.id + default_route_settings { + detailed_metrics_enabled = false + } +} + +resource "aws_apigatewayv2_deployment" "ApiGatewayV2Deployment3" { + api_id = aws_apigatewayv2_api.ApiGatewayV2Api.id +} + +resource "aws_apigatewayv2_deployment" "ApiGatewayV2Deployment4" { + api_id = aws_apigatewayv2_api.ApiGatewayV2Api.id +} + +resource "aws_apigatewayv2_route" "ApiGatewayV2Route" { + api_id = aws_apigatewayv2_api.ApiGatewayV2Api.id + api_key_required = false + authorization_type = "NONE" + route_key = "PUT /sondes/telemetry" + target = "integrations/${aws_apigatewayv2_integration.ApiGatewayV2Integration.id}" +} + +resource "aws_apigatewayv2_integration" "ApiGatewayV2Integration" { + api_id = aws_apigatewayv2_api.ApiGatewayV2Api.id + connection_type = "INTERNET" + integration_method = "POST" + integration_type = "AWS_PROXY" + integration_uri = aws_lambda_function.LambdaFunction.arn + timeout_milliseconds = 30000 + payload_format_version = "2.0" +} + +resource "aws_apigatewayv2_api_mapping" "ApiGatewayV2ApiMapping" { + api_id = aws_apigatewayv2_api.ApiGatewayV2Api.id + domain_name = aws_apigatewayv2_domain_name.ApiGatewayV2DomainName.id + stage = "$default" + api_mapping_key = "" +} + +resource "aws_apigatewayv2_domain_name" "ApiGatewayV2DomainName" { + domain_name = "api.${local.domain_name}" + domain_name_configuration { + certificate_arn = aws_acm_certificate_validation.CertificateManagerCertificate.certificate_arn + endpoint_type = "REGIONAL" + security_policy = "TLS_1_2" + } +} + +resource "aws_acm_certificate" "CertificateManagerCertificate" { + domain_name = local.domain_name + subject_alternative_names = [ + "*.${local.domain_name}" + ] + validation_method = "DNS" +} + +resource "aws_elasticsearch_domain" "ElasticsearchDomain" { + domain_name = "sondes-v2" + elasticsearch_version = "7.9" + cluster_config { + dedicated_master_count = 3 + dedicated_master_enabled = true + dedicated_master_type = "t3.small.elasticsearch" + instance_count = 2 + instance_type = "t3.small.elasticsearch" + zone_awareness_enabled = true + } + cognito_options { + enabled = true + identity_pool_id = aws_cognito_identity_pool.CognitoIdentityPool.id + role_arn = aws_iam_role.IAMRole3.arn + user_pool_id = aws_cognito_user_pool.CognitoUserPool.id + } + + access_policies = <