How to secure a Google Cloud Function with API Gateway and CORS? - google-cloud-functions

I created an API Gateway which uses the x-google-backend to a cloud functions.
When I tried to access it via browser I received a CORS error so I researched and find a solution by adding this to the OpenAPI config where the address part is the same as the cloud function.
options:
operationId: cors
x-google-backend:
address: https://europe-west3-myproject.cloudfunctions.net/api/query
responses:
'200':
description: A successful response
This works! So I removed the public access to the cloud function and gave the gateway service account access to it and tried again.
Which gave me a permission error. After research I found this post explaining the problem and giving me a solution to fix it.
The issue was that I call my define the cloud function with an additional path to call query. I added this to the OpenAPI config:
jwt_audience: https://europe-west3-myproject.cloudfunctions.net/api
So I tried it again in Postman and it works, however in the browser I now get again a CORS error.
So now I am at square one... what should I do?
Here is my complete OpenAPI config:
# openapi2-functions.yaml
swagger: '2.0'
info:
version: 1.0.0
schemes:
- https
produces:
- application/json
paths:
/query:
post:
operationId: api
parameters:
- in: "body"
name: "message"
schema:
$ref: '#/definitions/messasge'
x-google-backend:
address: https://europe-west3-myproject.cloudfunctions.net/api/query
jwt_audience: https://europe-west3-myproject.cloudfunctions.net/api
x-google-quota:
metricCosts:
"read-requests": 1
security:
- api_key: []
responses:
'200':
description: A successful response
schema:
type: string
options:
operationId: cors
x-google-backend:
address: https://europe-west3-myproject.cloudfunctions.net/api/query
responses:
'200':
description: A successful response
securityDefinitions:
# This section configures basic authentication with an API key.
api_key:
type: "apiKey"
name: "key"
in: "query"
x-google-management:
metrics:
# Define a metric for read requests.
- name: "read-requests"
displayName: "Read requests"
valueType: INT64
metricKind: DELTA
quota:
limits:
# Define the limit or the read-requests metric.
- name: "read-limit"
metric: "read-requests"
unit: "1/min/{project}"
values:
STANDARD: 100
definitions:
chatmessage:
type: "object"
properties:
id:
type: string
description: session id
example: "2vr34524tg3"
query:
type: string
description: message
example: "Hello"
required:
- id
- query

According to the documentation Cross-Origin Resource Sharing (CORS) on Cloud Functions has some limitations:
CORS preflight requests are sent without an Authorization header, so they will be rejected on all non-public HTTP Functions. Because the preflight requests fail, the main request will also fail.
To overcome this limitation in your case the mentioned documentation recommends to deploy a Cloud Endpoints proxy and enable CORS. Also you might find useful the Support CORS documentation page for a description of available CORS support options

Related

Open Shift Confluent Operator : Failed to provision volume with StorageClass "managed-premium" AADSTS7000215: Invalid client secret provided

Zookeeper is unable to provision the pods on Open Shift :
The client id / secret has been configured in the secrets.
It is able to pick up the client id correctly
The client id secret is valid not expired.
Seeing this issue :
Failed to provision volume with StorageClass "managed-premium": Retriable: false, RetryAfter: 0s, HTTPStatusCode: 401, RawError: Retriable: false, RetryAfter: 0s, HTTPStatusCode: 401, RawError: azure.BearerAuthorizer#WithAuthorization: Failed to refresh the Token for request to https://management.azure.com/subscriptions/<XXXXX>/resourceGroups/<XXXXX>/providers/Microsoft.Compute/disks/<XXXXX>?api-version=2019-11-01: StatusCode=401 -- Original Error: adal: Refresh request failed. Status Code = '401'. Response body: {"error":"invalid_client","error_description":"AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app '<YYYYYYY>'.\r\nTrace ID: <BLAHHHHHH>\r\nCorrelation ID: <BLAHHHHHHHH>\r\nTimestamp: 2022-11-02 16:46:19Z","error_codes":[7000215],"timestamp":"2022-11-02 16:46:19Z","trace_id":"<BLAHHHHHH>","correlation_id":"<BLAHHHHHH>","error_uri":"https://login.microsoftonline.com/error?code=7000215"} Endpoint https://login.microsoftonline.com/<BLAHHHHHH>/oauth2/token
Verified credentials are valid and not expired

Google Cloud Platform SQL database creation

I need to create, among other items, an SQL instance on the google cloud platform. I am required to create the database using Jinja files.
My Yaml file
imports:
- path: companyInstance.jinja
resources:
# Creates a database instance
- name: dbinstance11
type: companyInstance.jinja
My companyInstance.jinja
resources:
- name: test
type: sqladmin.v1beta4.instance
properties:
zone: europe-west1
settings:
- tier: db-custom-4-15360
Currently, this should all work as far as I can tell but on a full deployment, I get an error message claiming that type is given an array type instead of object.
The full error is below:
ERROR: (gcloud.deployment-manager.deployments.create) Error in Operation [operation-169876402531-756fgfg342844d-6gd6ebb6-8bb655a]: errors:
- code: CONDITION_NOT_MET
location: /deployments/dep/resources/test->$.properties
message: |
error: instance type (array) does not match any allowed primitive type (allowed: ["object"]) level: "error"
schema: {"loadingURI":"#","pointer":"/schemas/Settings"}
instance: {"pointer":"/settings"}
domain: "validation"
keyword: "type"
found: "array"
expected: ["object"]

How to inspect a json response from Ansible URI call

I have a service call that returns system status in json format. I want to use the ansible URI module to make the call and then inspect the response to decide whether the system is up or down
{"id":"20161024140306","version":"5.6.1","status":"UP"}
This would be the json that is returned
This is the ansible task that makes a call:
- name: check sonar web is up
uri:
url: http://sonarhost:9000/sonar/api/system/status
method: GET
return_content: yes
status_code: 200
body_format: json
register: data
Question is how can I access data and inspect it as per ansible documentation this is how we store results of a call. I am not sure of the final step which is to check the status.
This works for me.
- name: check sonar web is up
uri:
url: http://sonarhost:9000/sonar/api/system/status
method: GET
return_content: yes
status_code: 200
body_format: json
register: result
until: result.json.status == "UP"
retries: 10
delay: 30
Notice that result is a ansible dictionary and when you set return_content=yes the response is added to this dictionary and is accessible using json key
Also ensure you have indented the task properly as shown above.
You've made the right first step by saving the output into a variable.
The next step is to use either when: or failed_when: statement in your next task, which will then switch based on the contents of the variable. There are a whole powerful set of statements for use in these, the Jinja2 builtin filters, but they are not really linked well into the Ansible documentation, or summarised nicely.
I use super explicitly named output variables, so they make sense to me later in the playbook :) I would probably write yours something like:
- name: check sonar web is up
uri:
url: http://sonarhost:9000/sonar/api/system/status
method: GET
return_content: yes
status_code: 200
body_format: json
register: sonar_web_api_status_output
- name: do this thing if it is NOT up
shell: echo "OMG it's not working!"
when: sonar_web_api_status_output.stdout.find('UP') == -1
That is, the text "UP" is not found in the variable's stdout.
Other Jinja2 builtin filters I've used are:
changed_when: "'<some text>' not in your_variable_name.stderr"
when: some_number_of_files_changed.stdout|int > 0
The Ansible "Conditionals" docs page has some of this info. This blog post was also very informative.
As per documentation at https://docs.ansible.com/ansible/latest/modules/uri_module.html
Whether or not to return the body of the response as a "content" key in the dictionary result. Independently of this option, if the reported Content-type is "application/json", then the JSON is always loaded into a key called json in the dictionary results.
---
- name: Example of JSON body parsing with uri module
connection: local
gather_facts: true
hosts: localhost
tasks:
- name: Example of JSON body parsing with uri module
uri:
url: https://jsonplaceholder.typicode.com/users
method: GET
return_content: yes
status_code: 200
body_format: json
register: data
# failed_when: <optional condition based on JSON returned content>
- name: Print returned json dictionary
debug:
var: data.json
- name: Print certain element
debug:
var: data.json[0].address.city

AuthZForce-PEP-IDM Always allow access even when user doesnt have permission for specific resource

I created user and gave him only one role.(Member)
Currently this role doesn't have any permission with any Http verb nor path.
This is my user:
{
organizations: [1]
0: {
website: ""
description: "AREAS"
roles: [1]
0: {
name: "Member"
id: "09dc1bdba42c48de9e15e88816284cbc"
}-
-
enabled: true
id: "363ac390cfc94aa293e02547afa78256"
domain_id: "default"
name: "AREAS"
}-
-
displayName: "root"
roles: [0]
app_id: "aea8f4a70b87422cb48068db9f0c6aea"
email: "root"
id: "root"
}
Now, when i try to do GET request on address: http://localhost/parameters/search_tables/
for which this user don't have permission,
it allows me access and redirects me nonetheless.
This is log from pep proxy:
2015-11-13 14:55:53.446 - INFO: IDM-Client - Checking token with IDM...
2015-11-13 14:55:53.484 - INFO: AZF-Client - Checking auth with AZF...
2015-11-13 14:55:53.484 - INFO: AZF-Client - Checking authorization
to roles [ '09dc1bdba42c48de9e15e88816284cbc' ] to do GET
on parameters/search_tables/ and app aea8f4a70b87422cb48068db9f0c6aea
2015-11-13 14:55:53.508 - INFO: Root - Access-token OK. Redirecting to app...
Refused to set unsafe header "accept-encoding"
Refused to set unsafe header "cookie"
My config file regarding authorization is:
config.azf = {
enabled: true,
host: '192.168.4.180',
port: 8080,
path: '/authzforce/domains/afb096b2-8951-11e5-980f-6bf3c4dac98a/pdp'
};
config.public_paths = [];
config.tokens_engine = 'oauth2';
My Pap policy is:
<PolicySet PolicySetId="default" Version="1.0"
PolicyCombiningAlgId="urn:oasis:names:tc:xacml:1.1:policy-combining-
algorithm:ordered-permit-overrides">
<Target />
<Policy PolicyId="permit-all" Version="1.0"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.1:rule-combining-
algorithm:ordered-permit-overrides">
<Target />
<Rule RuleId="permit-all" Effect="Permit" />
</Policy>
</PolicySet>
How should i formulate my PAP policy to enable authorization level2, to use only http verb and resource path for authorization?
By default, Authzforce PAP permits all when no policy is added. Check if your PAP has the right information:
GET
/domains/{domainId}/pap/policySet
Edit 1:
In order to be able to connect with Authzforce, you need to configure some Authzforce parameters into your IdM instance:
ACCESS_CONTROL_URL at fiware-idm/horizon/openstack_dashboard/local/local_settings.py
and
ACCESS_CONTROL_MAGIC_KEY at fiware-idm/horizon/openstack_dashboard/local/local_settings.py
Then, just go to IdM, and check that the permissions and roles are well configured. Sometimes, you have to 'trigger' the policy generation in IdM by going to your application -> manage roles and just click 'save' to trigger the XACML generation.

Convert Json reponse in swagger with description

I try to specify the response from GET method with Swagger Editor.
But when I look in Swagger UI, the response JSON doesn't show.
My declaration swagger :
/clients/{id}:
get:
consumes:
- application/hal+json
produces:
- application/hal+json
# This is array of GET operation parameters:
parameters:
# An example parameter that is in query and is required
- name: id
in: path
required: true
type: string
# Expected responses for this operation:
responses:
# Response code
200:
description: Succes
# A schema describing your response object.
# Use JSON Schema format
schema:
example:
application/json: |
- {"produits":[{"idOffre":{"codeBanque":"038","identifiant":"123"},"idProduit":{"codeBanque":"061","identifiant":"123"}},{"idOffre":{"code":"038","identifiant":"123"},"idProduit":{"code":"061","identifiant":"123"}}]}
.....
In Swagger UI , the box where is written Response Class (Status 200) > Model Schema there is an empty json like that -> {}
I'm not sure swagger-ui supports examples, however I fixed some errors in you swagger extract:
example renamed examples
examples at same indentation level as schema (in you example, example is processed as a property of the response schema, I'm not sure this is what you want)
schema must describe response model, complete TODO
Fixed version:
swagger: '2.0'
info:
title: Clients
description: API
version: "1.0.0"
host: api.test.com
schemes:
- https
basePath: /v1
produces:
- application/json
paths:
/clients/{id}:
get:
consumes:
- application/hal+json
produces:
- application/hal+json
parameters:
- name: id
in: path
required: true
type: string
responses:
200:
description: Succes
schema:
type: array
items:
properties:
produits:
type: string
description: TODO
examples:
application/json: |
- {"produits":[{"idOffre":{"codeBanque":"038","identifiant":"123"},"idProduit":{"codeBanque":"061","identifiant":"123"}},{"idOffre":{"code":"038","identifiant":"123"},"idProduit":{"code":"061","identifiant":"123"}}]}