How to enable per-path level api-key auth for all version when deploying multiple versions to same configuration in Google Clould Endpoint - authentication

I deployed 2 versions of openapi.yaml file to Google Cloud Endpoint using the Cloud Endpoint's versioning feature(i.e gcloud endpoints services deploy openapi_v1.yaml openapi_v2.yaml). Each version of the yaml file contains a version number and basepath different from the other, one endpoint that use api-key authentication, and definition for api-key authentication tag. After deployed to Endpoint, the configuration shows both yaml file, however deploying an api to Cloud Run ESPv2 using this configuration will only have api-key authentication turned on for the newer version.
Does anyone know if this is a known bug, or there is something else I need to do to enable authentication for all versions?
The .yaml file looks like the following. The two versions I used to test on are identical except version and bathpath:
swagger: "2.0"
info:
description: "This API is used to connect 3rd-party ids to a common user identity"
version: "1.0"
title: "****"
host: "uie-dot-user-id-exchange.appspot.com"
basePath: "/v1"
...
- "https"
x-google-allow: all
paths:
...
/ids/search:
get:
operationId: "id_search"
produces:
- "application/json"
security:
- api_key: []
tags:
- "Ids"
summary: "Privileged endpoint. Provide any id (3rd party or otherwise) and get a hash of all ids associated with it."
parameters:
- in: "query"
name: "id_type"
description: "Type of id to search"
required: true
type: string
- in: "query"
name: "id_value"
description: "Value of id to search"
required: true
type: string
responses:
200:
description: "AssociatedIdsHash"
schema:
$ref: '#/definitions/AssociatedIdsHash'
400:
description: "Bad request. Requires both id_type and id_value query parameters."
401:
description: "Unauthorized. Please provide a valid api-key in the \"api-key\" header."
404:
description: "Not found - no entry found for key provided"
...
################ SECURITY DEFINITIONS ################
securityDefinitions:
# This section configures basic authentication with an API key.
api_key:
type: "apiKey"
name: "key"
in: "query"
I tried to make the api-key work in v1 and v2 but it only works in version 2.

Related

Google Cloud Platform swagger openapi config yaml file isn't properly rejecting requests that don't contain my api key in the header

I have this config file for my Google Cloud Platform API Gateway endpoint:
swagger: '2.0'
info:
title: api-1
description: API Gateway First for Testing
version: 1.0.0
securityDefinitions:
api_key_header:
type: apiKey
name: key
in: header
schemes:
- https
produces:
- application/json
paths:
/endpoint1:
post:
summary: Simple echo service
operationId: echo-1
x-google-backend:
address: https://<CLOUD FUNCTION GEN 2 NAME>-<MORE IDENTIFYING INFO>-uc.a.run.app
security:
- api_key_header: []
responses:
'200':
description: OK
As you can see, I'm trying to require an API key in order for my server to call the API safely. In my opinion, an API key is necessary for security to prevent someone from figuring out my endpoint and spaming the GCP function.
I created an API key to use for this API endpoint (I censored a lot of data for privacy reasons):
I tried to call the endpoint in Postman like this:
curl --location --request POST 'https://<API CALLABLE ENDPOINT>.uc.gateway.dev/endpoint1' \
--header 'X-goog-api-key: <MY API KEY HERE>' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"name": "Test1"
}'
The problem is that the Postman request works... always lol. No matter what incorrect API key I use for the header...
I noticed that there is no place where I'm directly referencing my API key name. I'm not sure where I'd put this. How do I alter this API Gateway to properly reject requests that do not contain the correct API key?
All available formats are specified on this documentation.
When requesting Api Key through the header, you have to match a specific name which is "x-api-key".
So for your openapi file, it gives the following securityDefinitions:
securityDefinitions:
api_key_header:
type: "apiKey"
name: "x-api-key"
in: "header"
And the curl request should have this header then:
--header 'x-api-key: <MY API KEY HERE>'

Unable to configure GCP API Gateway where endpoint is outside of GCP

I am trying to configure API Gateway on GCP console where the APIs are exposed at external web URL endpoint. I wish to fetch them and store the results in json in GCP cloud storage bucket. So the flow to retrive info is - External URI endpoint -> API Gateway (gcp) -> gcp storage bucket
Below is the URL that has exposed the APIs. I have the key and the element information. I am able to retrive the values via Power BI as well as curl command but I am unable to configure the API successfully on the GCP API Gateway service to fetch the same.
URL - https://xxxx.xxxxxxxx.com/cost/api/organizations/control-elements
Below curl command works -
curl -H X-User-Access-Token:xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx https://xxxx.xxxxxxxx.com/cost/api/organizations/control-elements
Below is the openAPI specs file that is being provided on the console
# openapi2-functions.yaml
swagger: '2.0'
info:
title: API_ID description
description: Sample API on API Gateway backend
version: 1.0.0
schemes:
- https
produces:
- application/json
host: 'https://xxxx.xxxxxxxx.com/cost/api/organizations/control-elements'
paths:
/control-elements:
get:
summary: Greet a user
operationId: control-elements
security:
- api_key: []
responses:
'200':
description: A successful response
schema:
type: string
securityDefinitions:
api_key:
type: "apiKey"
name: "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
in: "query"
Error message -
Cannot convert to service config. 'location: "unknown location" kind: ERROR message: "Unable to parse the content. while parsing a block mapping\n in 'reader', line 2, column 1:\n swagger: '2.0'\n ^\nexpected , but found ''\n in 'reader', line 11, column 98:\n ... xxxxx/xxxxx/control-element's\n ^\n\n at [Source: (StringReader); line: 11, column: 98]" ' com.google.apps.framework.request.BadRequestException: Cannot convert to service config. 'location: "unknown location" kind: ERROR message: "Unable to parse the content. while parsing a block mapping\n in 'reader', line 2, column 1:\n swagger: '2.0'\n ^\nexpected , but found ''\n in 'reader', line 11, column 98:\n ... xxxxx/xxxxx/control-element's\n ^\n\n at [Source: (StringReader); line: 11, column: 98]" '
Attached is the screenshot of the values entered in the API Gateway service. Please advise on what is being missed over here
Data feed for API gateway service is as shown in screenshot
I tried altering the config in various ways. My service account has APIGateway-Admin access too. Curl as well as through Power BI, I am able to fetch API information from the mentioned URL too

A few questions about authentication and authorization with Kong jwt in microservices architecture

As a newbie in microservices architecture, I need to ask a few questions about implementing JWT authentication using Kong.
The architecture of my application looks like in the picture below:
So far I have only used Kong as a proxy and load balancer. The Authentication Service was responsible for creating the token. The token was created during registration and logging in. During registration or logging in, the authentication service asked the user service, and the user service checked the user's data in the mongodb database. Each endpoint from the other services had to receive a JWT in the header and had a function along with a secret which decoded the token. However, it seems to me that this is an unnecessary duplication of code and the whole process of creating and decoding JWT may or even should be done in Kong with JWT plugin.
I tried to follow a couple of tutorials and YouTube guides just like this one:
JWT Kong Gateway
Unfortunately each of the tutorials shows how to create a JWT only for a single consumer, without Kong being connected to the base.
My kong.yml file:
_format_version: "3.0"
_transform: true
services:
- name: building_service
url: http://building_service/building
routes:
- name: building_service_route
paths:
- /building
- name: user_service
url: http://user_service/user
routes:
- name: user_service_route
paths:
- /user
- name: role_service
url: http://role_service/role
routes:
- name: role_service_route
paths:
- /role
- name: task_service
url: http://task_service/task
routes:
- name: task_service_route
paths:
- /task
- name: authorization_service
url: http://authorization_service/authorization
routes:
- name: authorization_service_route
paths:
- /authorization
plugins:
- name: jwt
route: building_service_route
enabled: true
config:
key_claim_name: kid
claims_to_verify:
- exp
# consumers:
# - username: login_server_issuer
# jwt_secrets:
# - consumer: login_server_issuer
# secret: "secret-hash-brown-bear-market-rate-limit"
- name: bot-detection
- name: rate-limiting
config:
minute: 60
policy: local
Kongo service in docker-compose.yml:
services:
kong:
build: ./App/kong
volumes:
- ./App/kong/kong.yml:/usr/local/kong/declarative/kong.yml
container_name: kong
environment:
KONG_DATABASE: 'off'
KONG_PROXY_ACCESS_LOG: '/dev/stdout'
KONG_ADMIN_ACCESS_LOG: '/dev/stdout'
KONG_PROXY_ERROR_LOG: '/dev/stderr'
KONG_ADMIN_ERROR_LOG: '/dev/stderr'
KONG_ADMIN_LISTEN: "0.0.0.0:8001, 0.0.0.0:8444 ssl"
KONG_DECLARATIVE_CONFIG: "/usr/local/kong/declarative/kong.yml"
command: "kong start"
networks:
- api-network
ports:
- "8000:8000"
- "8443:8443"
- "127.0.0.1:8001:8001"
- "127.0.0.1:8444:8444"
List of my questions:
How authentication service should connect to Kong and create JWT with chosen user (as I understand consumer) data?
Should Kong be somehow connected to database to get required user data and create secret?
How to decode JWT with kong and transfer it to other services in header?
Can anyone provide an example of how to achieve desired result?
Do I misunderstood something about JWT or Kong and what I want to achieve is impossible?
If you can consider using Keycloak for user management, then you can have a look at the jwt-keycloak plugin:
https://github.com/gbbirkisson/kong-plugin-jwt-keycloak

Swagger file security scheme defined but not in use

I have a Swagger 2.0 file that has an auth mechanism defined but am getting errors that tell me that we aren't using it. The exact error message is “Security scheme was defined but never used”.
How do I make sure my endpoints are protected using the authentication I created? I have tried a bunch of different things but nothing seems to work.
I am not sure if the actual security scheme is defined, I think it is because we are using it in production.
I would really love to have some help with this as I am worried that our competitor might use this to their advantage and steal some of our data.
swagger: "2.0"
# basic info is basic
info:
version: 1.0.0
title: Das ERP
# host config info
# Added by API Auto Mocking Plugin
host: virtserver.swaggerhub.com
basePath: /rossja/whatchamacallit/1.0.0
#host: whatchamacallit.lebonboncroissant.com
#basePath: /v1
# always be schemin'
schemes:
- https
# we believe in security!
securityDefinitions:
api_key:
type: apiKey
name: api_key
in: header
description: API Key
# a maze of twisty passages all alike
paths:
/dt/invoicestatuses:
get:
tags:
- invoice
summary: Returns a list of invoice statuses
produces:
- application/json
operationId: listInvoiceStatuses
responses:
200:
description: OK
schema:
type: object
properties:
code:
type: integer
value:
type: string
securityDefinitions alone is not enough, this section defines available security schemes but does not apply them.
To actually apply a security scheme to your API, you need to add security requirements on the root level or to individual operations.
security:
- api_key: []
See the API Keys guide for details.

How to implement redirect (301 code) mock in serverless framework config (for AWS) without lambda

I'd like that the root path of my API redirect (301) to completely another site with docs. So I have a lambda at e.g /function1 path and the / should return code 301 with another location. And I'd like to do it without another lambda.
This is exactly what is described here, but via aws command line tool. I tried this approach - it works perfectly, but I'd like to configure such API gateway mock via serverless framework config.
Fortunately, the series of CLI commands you linked to can be reproduced in CloudFormation, which can then be dropped into the Resources section of your Serverless template.
In this example, a GET to /function1 will invoke a lambda function, while a GET to / will return a 301 to a well-known search engine.
service: sls-301-mock
provider:
name: aws
runtime: nodejs12.x
stage: dev
region: us-east-1
functions:
hello:
handler: handler.hello
events:
- http:
path: function1
method: get
resources:
Resources:
Method:
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: GET
ResourceId:
!GetAtt ApiGatewayRestApi.RootResourceId
RestApiId:
Ref: ApiGatewayRestApi
AuthorizationType: NONE
MethodResponses:
- ResponseModels: {"application/json":"Empty"}
StatusCode: 301
ResponseParameters:
"method.response.header.Location": true
Integration:
Type: MOCK
RequestTemplates:
"application/json": "{\n \"statusCode\": 301\n}"
IntegrationResponses:
- StatusCode: 301
ResponseParameters:
"method.response.header.Location": "'https://google.com'"
Tested with:
Framework Core: 1.62.0
Plugin: 3.3.0
SDK: 2.3.0
Components Core: 1.1.2
Components CLI: 1.4.0
Notes
ApiGatewayRestApi is, by convention, the logical name of the API Gateway Stage resource created by Serverless on account of the http event.
Relevant CloudFormation documentation
ApiGateway::Method
ApiGateway::Method Integration
EDIT
This answer is not as verbose, and uses an http event instead of the Resources section. I haven't tested it, but it may also work for you.
Managed to achieve it with referring one function twice. But see also reply of Mike Patrick - looks more universal
...
events:
- http:
path: main/root/to/the/function
method: get
cors: true
- http:
path: /
method: get
integration: mock
request:
template:
application/json: '{"statusCode": 301}'
response:
template: redirect
headers:
Location: "'my-redirect-url-note-the-quotes-they-are-important'"
statusCodes:
301:
pattern: ''