how to make Google Cloud Armor interpret recaptcha score - google-cloud-armor

I have GKE applications in following setup:
front app works on example.com
backend app works on api.example.com
I expose those loads via Ingress and all looks cool. I want to protect application with Cloud Armor. I added annotation to api service. I can confirm that if policy has just one rule "deny all IPs" I cannot reach backend endpoints and if I change rule to "allow all IPs" I can. So GCA itself works ok.
I tried to connect reCaptcha Enterprise and interpret it's score with Google Cloud Armor but I cannot make it work. I created following rules but whatever values I add token.recaptcha.score doesn't seem to be interpreted at all.
So in presented example I will always be blocked even if I make rule ridiculously small like "> 0.1". Front sends X-Recaptcha-Token to backend so it looks like I did everything correctly.
Only thing I'm not sure about is if this allow rule is correctly defined. GCP Logging shows that policy was applied but I don't know exactly which rule:
{
"insertId": "uxxxv",
"jsonPayload": {
"enforcedSecurityPolicy": {
"outcome": "DENY",
"configuredAction": "DENY",
"priority": 2147483647,
"name": "login-security-policy"
},
"#type": "type.googleapis.com/google.cloud.loadbalancing.type.LoadBalancerLogEntry",
"statusDetails": "denied_by_security_policy"
},
"httpRequest": {
"requestMethod": "OPTIONS",
"requestUrl": "https://api.example.com/v1/graphs?pageSize=10&orderBy=created_at%20desc&key=AXXXXXXE",
"requestSize": "330",
"status": 403,
"responseSize": "228",
"userAgent": "XXX",
"remoteIp": "XX.XX.XX.XX",
"referer": "https://example.com/",
"latency": "0.220009s"
},
"resource": {
"type": "http_load_balancer",
"labels": {
"zone": "global",
"target_proxy_name": "k8s2-ts-dxxxd-default-main-ixxxq",
"backend_service_name": "k8s-be-3xxx9--9xxx9",
"forwarding_rule_name": "k8s2-fs-dxxxd-default-main-ixxxq",
"project_id": "xxx",
"url_map_name": "k8s2-um-dxxxd-default-main-ixxxq"
}
},
"timestamp": "2021-12-21T12:22:28.505728Z",
"severity": "WARNING",
"logName": "projects/xxx/logs/requests",
"trace": "projects/xxx/traces/bxxx4",
"receiveTimestamp": "2021-12-21T12:22:28.925285233Z",
"spanId": "cxxx4"
}
I just assume that field jsonPayload.enforcedSecurityPolicy.priority is pointing to default rule which means that Allow rule doesn't work.
Also reCaptcha key has been enabled by emailing Google according to documentation.

The HTTP method that is falling through to the default rule is OPTIONS. The OPTIONS method is often used by CORS, so you normally want those requests to get through.
Add a rule that allows HTTP method OPTIONS based upon request.method == 'OPTIONS'.
Or modify your existing rule to to only check if the method is GET, PUT, POST (specify the methods you need to validate reCaptcha).
Cloud Armor Rule Attributes

Related

HTTP Error 500 when running cloud scheduler to HTTP trigger cloud function to run pipeline

I'm trying to follow this tutorial about setting up a schedule to trigger your pipeline using a cloud function and scheduler. I've followed the tutorial up to the letter, to my knowledge. I made sure the pipeline runs without errors, and set up the cloud function. For setting up the job:
I set the frequency to 0 9 * * 1
Set the URL to https://us-central1-[redacted].cloudfunctions.net/hello-world-scheduled-pipeline-function
For the Body section, following the guide I set
{
"pipeline_spec_uri": "gs://[redacted]/test/tab_classif_pipeline_test.json",
"parameter_values": {
"greet_name": "test"
}
}
Added OIDC token, set it to a service account that can invoke cloud functions (and other job scheduler permissions), and left all other fields to default.
After trying to run it manually, I get the following error, which I cannot for the life of me interpret:
{
"insertId": "j5h0k0flkeq6j",
"jsonPayload": {
"url": "https://us-central1-[redacted].cloudfunctions.net/hello-world-scheduled-pipeline-function",
"jobName": "projects/[redacted]/locations/us-central1/jobs/hello-world-cloud-scheduler",
"targetType": "HTTP",
"status": "INTERNAL",
"#type": "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished"
},
"httpRequest": {
"status": 500
},
"resource": {
"type": "cloud_scheduler_job",
"labels": {
"job_id": "hello-world-cloud-scheduler",
"project_id": "[redacted]",
"location": "us-central1"
}
},
"timestamp": "2022-04-13T15:09:04.120977064Z",
"severity": "ERROR",
"logName": "projects/[redacted]/logs/cloudscheduler.googleapis.com%2Fexecutions",
"receiveTimestamp": "2022-04-13T15:09:04.120977064Z"
}
To my knowledge, I've been following this guide perfectly, so why isn't this working? Is there something wrong with how I set things up in the Body section? What could it be?

Native way of view apigateway documentation in browser

I have an public AWS apigateway created providing a swagger file.
To document the API I have added to the swagger the following section:
"x-amazon-apigateway-documentation": {
"documentationParts": [
{
"location": {
"type": "API"
},
"properties": {
"description": "This is the API description"
}
},
{
"location": {
"type": "METHOD",
"method": "GET",
"path": "/foo/{bar}"
},
"properties": {
"description": "This is the method description"
}
}
]
}
Then I have published the documentation version 1.0 through AWS console.
Reached this point I want to give anyone the URL of my API documentation that ideally should be rendered in the browser in a nice way.
But, checking AWS docs regarding apigateway documentation I only find one way to access to it, that is using another AWS provided API:
http://apigateway.eu-central1.amazonaws.com/restapis/TheIdOfMyApiGateway/documentation/parts
Additionally, I should set some access keys in the request to retrieve it, making impossible for one agnostic user to simply view it in the browser setting no additional headers in the request.
Is there any way to achieve my aim?

Create tagged vm instance snapshots

I'm trying to create snapshots of my vm instance on google cloud platform with a custom tag, but it's currently not working as expected. I'm sending the following Post request body to API referring to this documentation Google docs
{
"name":"<SnapshotName>",
"labels": {
"<LabelKey>":"<LabelValue>"
}
}
this gives me a positive 200 OK response, but no label appears.
{
"kind": "compute#operation",
"id": "<id>",
"name": "<name>",
"zone": "<Zone Link>",
"operationType": "createSnapshot",
"targetLink": "<Target Link>",
"targetId": "<Target ID>",
"status": "PENDING",
"user": "<User>",
"progress": 0,
"insertTime": "<Time>",
"selfLink": "<Self Link>"
}
additionally I tried to use syntax described in "Labeling Resources" documentation Google Labeling Resources
{
"name":"<SnapshotName>",
"labels": [{
"<Key>":"<LabelKey>"
"<Value>":"<LabelValue>"
}]
}
this gave me the same result.
In web interface it's possible to create snapshots and label it manually, but I would like to create them with a custom label via API.
Am I doing something wrong, or is it just broken?

ApiGateway CloudFormation without lambda

I am trying to create a template so that when i call api/divide/inputvalue, The api sends back response from DynamoDB which corresponds to inputvalue mapping.
Its pretty straight forward since i am fetching value directly from db without any business logic hence I don't need any lambda. But all the examples that I google or all tutorials they are using lambdas and i am now lost that how can i make it working without lambda
This is what I have so far. There is bug in this template right now since I haven't provided Uri in ApiGateway::Method. Which is what I am currently stuck at.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Deployment": {
"Type": "AWS::ApiGateway::Deployment",
"Properties": {
"RestApiId": { "Ref": "restApiName" },
"Description": "First Deployment",
"StageName": "StagingStage"
},
"DependsOn" : ["restApiMethod"]
},
"restApiMethod": {
"Type": "AWS::ApiGateway::Method",
"Properties": {
"AuthorizationType": "NONE",
"HttpMethod": "GET",
"ResourceId": {"Ref": "apiRestResource"},
"RestApiId": {"Ref": "restApiName"},
"Integration": {
"Type": "AWS",
"IntegrationHttpMethod": "GET",
"IntegrationResponses": [{"StatusCode": 200}],
"Uri": { "Fn::Sub":"arn.aws.apigateway:${AWS::Region}:dynamodb:action/${restApiName.Arn}"}
},
"MethodResponses": [{"StatusCode": 200}]
},
"DependsOn": ["apiRestResource"]
},
"apiRestResource": {
"Type": "AWS::ApiGateway::Resource",
"Properties": {
"RestApiId": {"Ref": "restApiName"},
"ParentId": {
"Fn::GetAtt": ["restApiName","RootResourceId"]
},
"PathPart": "divide"
},
"DependsOn": ["restApiName"]
},
"restApiName": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Name": "CalculationApi"
}
}
}
}
According to the documentation, the Uri property is structured as follows for AWS service-proxy integration types:
If you specify AWS for the Type property, specify an AWS service that follows the form: arn:aws:apigateway:region:subdomain.service|service:path|action/service_api. For example, a Lambda function URI follows the form: arn:aws:apigateway:region:lambda:path/path. The path is usually in the form /2015-03-31/functions/LambdaFunctionARN/invocations. For more information, see the uri property of the Integration resource in the Amazon API Gateway REST API Reference.
The uri API Gateway property reference provides more details:
For AWS integrations, the URI should be of the form arn:aws:apigateway:{region}:{subdomain.service|service}:{path|action}/{service_api}. Region, subdomain and service are used to determine the right endpoint. For AWS services that use the Action= query string parameter, service_api should be a valid action for the desired service. For RESTful AWS service APIs, path is used to indicate that the remaining substring in the URI should be treated as the path to the resource, including the initial /.
For an AWS service proxy to the dynamodb service calling the Query Action, the Uri should be something like this (using the YAML short-form of Fn::Sub to insert a Ref for the current AWS region):
!Sub "arn:aws:apigateway:${AWS::Region}:dynamodb:action/Query"
As for your broader use-case of using API Gateway to access DynamoDB without using Lambda functions, refer to Andrew Baird's tutorial blog post, "Using Amazon API Gateway as a Proxy for DynamoDB", and translate the specified Management Console steps to corresponding CloudFormation template resources.

AWS API Gateway and EC2 Service Proxy

I am trying to POST a json string to API Gateway and in turn have API Gateway send the JSON to an EC2 server.
My issue is I can't find good documentation from Amazon on how to accomplish this.
When I test the setup I get this
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response><Errors><Error><Code>InvalidHttpRequest</Code><Message>The HTTP request is invalid. Reason: Unable to parse request</Message></Error></Errors><RequestID>1fa47f52-d75c-4ff8-8992-3eac11a79015</RequestID></Response>"
Which means very little to me. I assume it is an issue with API Gateway trying to send the request to EC2 and it can't so it generates this error. So perhaps I am setting up the EC2 AWS Service Proxy in API Gateway incorrectly. Which is likely because I have no idea what I am supposed to set 'Action' to right now I have it pointing to the EC2 instance, only cause i don't see any other place to put that info.
This really shouldn't be that hard I have successfully done this thing connecting to Lambda and have looked through all the documentation and all I can find is this: http://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-aws-proxy.html#getting-started-aws-proxy-add-resources
Which is less than helpful for this scenario. Any Ideas?
I think you confused AWS Service Proxy and HTTP Service proxy.
API Gateway can forward API calls to different type of backends:
- a lambda function
- an AWS Service (see http://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html for an example)
- an existing API, running on AWS or on premises (your use case)
When defining you API, be sure to define a POST verb and point the Endpoint URL to your EC2 instance URL
I just made a test using the JSON POST service available online at http://gurujsonrpc.appspot.com/ and it works as expected.
Here is the Swagger export of my test API.
{
"swagger": "2.0",
"info": {
"version": "2016-04-11T20:46:13Z",
"title": "test"
},
"host": "c22wfjg4d7.execute-api.eu-west-1.amazonaws.com",
"basePath": "/prod",
"schemes": [
"https"
],
"paths": {
"/": {
"post": {
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "200 response",
"schema": {
"$ref": "#/definitions/Empty"
}
}
},
"x-amazon-apigateway-integration": {
"responses": {
"default": {
"statusCode": "200"
}
},
"uri": "http://gurujsonrpc.appspot.com/guru",
"httpMethod": "POST",
"type": "http"
}
}
}
},
"definitions": {
"Empty": {
"type": "object"
}
}
}