Google Cloud Endpoints does not restrict access to my API

2/3/2020

I've followed the google cloud endpoints with Google Kubernetes engine tutorial here: https://cloud.google.com/endpoints/docs/openapi/get-started-kubernetes-engine using my own docker image. The Kubernetes part works fine and I can access my services via the loadbalancer IP.

However, when I try to put my service behind cloud endpoints in order to secure it, the endpoint remains public and can be accessed without an API key. Here is my openapi.yaml, deployed with gcloud endpoints services deploy openapi.yaml:

swagger: "2.0"
info:
  description: "A test."
  title: "API test"
  version: "1.0.0"
host: "<test-api.endpoints.MY-PROJECT-ID.cloud.goog>"
x-google-endpoints:
- name: "<test-api.endpoints.MY-PROJECT-ID.cloud.goog>"
  target: "<MY LOADBALANCER IP>"
#require an API key to access project
security:
  - api_key: []
paths:
  /:
    get:
      summary: Return django REST default page
      description: test
      operationId: test
      responses:
        "200":
          description: OK
securityDefinitions:
  # This section configures basic authentication with an API key.
  api_key:
    type: "apiKey"
    name: "key"
    in: "query" 

When I try to access my service via the value for host (obscured because it is still open), it is still open and does not require an API key . Nothing is shown in the cloud endpoints logs either. As far as I understand, the configuration of openapi.yaml alone should be enough to restrict access?

-- millsy
google-cloud-endpoints
kubernetes

1 Answer

2/3/2020

Following this page (https://swagger.io/docs/specification/2-0/authentication/api-keys/), your security is misplaced. It should looks like this:

swagger: "2.0"
info:
  description: "A test."
  title: "API test"
  version: "1.0.0"
host: "<test-api.endpoints.MY-PROJECT-ID.cloud.goog>"
x-google-endpoints:
- name: "<test-api.endpoints.MY-PROJECT-ID.cloud.goog>"
  target: "<MY LOADBALANCER IP>"
#require an API key to access project
paths:
  /:
    get:
      security:
        - api_key: []
      summary: Return django REST default page
      description: test
      operationId: test
      responses:
        "200":
          description: OK
securityDefinitions:
  # This section configures basic authentication with an API key.
  api_key:
    type: "apiKey"
    name: "key"
    in: "query" 

Edit:

In case you want the api-key in the header, you have to change the definition but you can leave security in the place you declared:

swagger: "2.0"
info:
  description: "A test."
  title: "API test"
  version: "1.0.0"
host: "<test-api.endpoints.MY-PROJECT-ID.cloud.goog>"
x-google-endpoints:
- name: "<test-api.endpoints.MY-PROJECT-ID.cloud.goog>"
  target: "<MY LOADBALANCER IP>"
#require an API key to access project
security:
  - api_key: []
paths:
  /:
    get:
      summary: Return django REST default page
      description: test
      operationId: test
      responses:
        "200":
          description: OK
securityDefinitions:
  # This section configures basic authentication with an API key.
  api_key:
    type: "apiKey"
    name: "key"
    in: "header" 

I didn't understand which version you preferred, so I adjusted both.

-- Marco Massetti
Source: StackOverflow