Skip to content

API gateway: api-keys in webserver, gateway services and client sdk #1460

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 33 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
021a89c
Infra fixes
pcrespov Apr 22, 2020
50f2687
Fixes make run-devel
pcrespov Apr 22, 2020
29c4d35
api_version_prefix by api_vtag
pcrespov Apr 22, 2020
3a80a36
Fixes start_db not called
pcrespov Apr 22, 2020
6547e7a
Add helpers for fastapi
pcrespov Apr 22, 2020
e976ef5
Using new shortcuts
pcrespov Apr 22, 2020
31cffe8
Fixes logging
pcrespov Apr 22, 2020
ef9aa0a
Doc and minor cleanup
pcrespov Apr 22, 2020
59487c3
Bump version: 0.1.0 → 0.1.1
pcrespov Apr 22, 2020
2684511
improves make info and formatting
pcrespov Apr 22, 2020
85f9985
redoc: adds vender extensions
pcrespov Apr 22, 2020
820e59e
Minor
pcrespov Apr 23, 2020
36e14c3
Drafting client api sdk
pcrespov Apr 23, 2020
606e3b8
Kills processes in 8001 upon make down
pcrespov Apr 27, 2020
04ce0fc
Defining API entrypoints
pcrespov Apr 27, 2020
c8f3b2a
minimum tests pass
pcrespov Apr 27, 2020
5f10ab5
fixes frontend linter
pcrespov Apr 27, 2020
940b0fe
Minor
pcrespov Apr 28, 2020
d06526f
Cleanup front-end messages/labels
pcrespov Apr 28, 2020
c152577
Adds new table for client credentials api_keys
pcrespov Apr 28, 2020
c5b7c54
Added api-keys section on webserver API
pcrespov Apr 28, 2020
2941e63
Minors
pcrespov Apr 28, 2020
7385de9
Adding api-keys handlers
pcrespov Apr 28, 2020
1b151e2
Tests for api-keys pass
pcrespov Apr 28, 2020
57ae255
Minor fixes in API
pcrespov Apr 28, 2020
3ca2655
webserver api version: 0.4.0 → 0.5.0
pcrespov Apr 28, 2020
83b321e
updates codeowners
pcrespov Apr 28, 2020
3b8a694
connects front-end by @odeimaiz (#27)
odeimaiz Apr 28, 2020
656a1fe
Sets role-based access to allow only users to create tokens
pcrespov Apr 28, 2020
32f2c77
Tests access to new entrypoints
pcrespov Apr 28, 2020
1f819ef
Update responses
pcrespov Apr 28, 2020
d84d10e
webserver api version: 0.5.0 → 0.5.1
pcrespov Apr 28, 2020
00e9bf6
Minor cleanup
pcrespov Apr 28, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Makefile @pcrespov, @sanderegg
/scripts/demo @odeimaiz, @pcrespov
/scripts/json-schema-to-openapi-schema @sanderegg
/scripts/template-projects @odeimaiz, @pcrespov
/services/api-gateway @pcrespov
/services/catalog @pcrespov
/services/sidecar @pcrespov, @mguidon
/services/web/client @odeimaiz, @oetiker, @ignapas
Expand Down
78 changes: 78 additions & 0 deletions api/specs/webserver/openapi-auth.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,70 @@ paths:
"3XX":
description: redirection to specific ui application page

/auth/api-keys:
get:
summary: lists display names of API keys by this user
tags:
- authentication
operationId: list_api_keys
responses:
"200":
description: returns the display names of API keys
content:
application/json:
schema:
type: array
items:
type: string
"401":
description: requires login to list keys
"403":
description: not enough permissions to list keys

post:
summary: creates API keys to access public API
tags:
- authentication
operationId: create_api_key
requestBody:
description: user registration
content:
application/json:
schema:
$ref: "#/components/schemas/ApiKeyName"
responses:
"200":
description: Authorization granted returning API key
content:
application/json:
schema:
$ref: "#/components/schemas/ApiKeyGranted"
"400":
description: key name requested is invalid
"401":
description: requires login to create a key
"403":
description: not enough permissions to create a key

delete:
summary: deletes API key by name
tags:
- authentication
operationId: delete_api_key
requestBody:
description: deletes given api key by name
content:
application/json:
schema:
$ref: "#/components/schemas/ApiKeyName"
responses:
"204":
description: api key successfully deleted
"401":
description: requires login to delete a key
"403":
description: not enough permissions to delete a key

components:
responses:
DefaultErrorResponse:
Expand All @@ -221,3 +285,17 @@ components:
client_session_id:
type: string
example: 5ac57685-c40f-448f-8711-70be1936fd63
ApiKeyName:
type: object
properties:
display_name:
type: string
ApiKeyGranted:
type: object
properties:
display_name:
type: string
api_key:
type: string
api_secret:
type: string
6 changes: 4 additions & 2 deletions api/specs/webserver/openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
openapi: 3.0.0
info:
title: "osparc-simcore RESTful API"
version: 0.4.0
version: 0.5.1
description: "RESTful API designed for web clients"
contact:
name: IT'IS Foundation
Expand Down Expand Up @@ -49,7 +49,7 @@ paths:
# DIAGNOSTICS ---------------------------------------------------------
/:
$ref: "./openapi-diagnostics.yaml#/paths/~1"

/health:
$ref: "./openapi-diagnostics.yaml#/paths/~1health"

Expand Down Expand Up @@ -85,6 +85,8 @@ paths:
/auth/confirmation/{code}:
$ref: "./openapi-auth.yaml#/paths/~1auth~1confirmation~1{code}"

/auth/api-keys:
$ref: "./openapi-auth.yaml#/paths/~1auth~1api-keys"
# USER SETTINGS ------------------------------------------------------------------

/me:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Adds api_keys table

Revision ID: 16ee7d73b9cc
Revises: f3555bb4bc34
Create Date: 2020-04-28 08:11:42.785688+00:00

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '16ee7d73b9cc'
down_revision = 'f3555bb4bc34'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('api_keys',
sa.Column('id', sa.BigInteger(), nullable=False),
sa.Column('display_name', sa.String(), nullable=False),
sa.Column('user_id', sa.BigInteger(), nullable=False),
sa.Column('api_key', sa.String(), nullable=False),
sa.Column('api_secret', sa.String(), nullable=False),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('display_name', 'user_id', name='display_name_userid_uniqueness')
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('api_keys')
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
""" API keys to access public gateway


These keys grant the client authorization to the API resources

+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
|client | | Owner | Authorization request
| |<-(B)-- Authorization Grant ---| |
+--------+ +---------------+

"""
import sqlalchemy as sa

from .base import metadata
from .users import users

api_keys = sa.Table(
"api_keys",
metadata,
sa.Column("id", sa.BigInteger, nullable=False, primary_key=True),
sa.Column("display_name", sa.String, nullable=False),
sa.Column(
"user_id",
sa.BigInteger,
sa.ForeignKey(users.c.id, ondelete="CASCADE"),
nullable=False,
),
sa.Column("api_key", sa.String, nullable=False),
sa.Column("api_secret", sa.String, nullable=False),
sa.UniqueConstraint(
"display_name", "user_id", name="display_name_userid_uniqueness"
),
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .models.user_to_projects import user_to_projects
from .models.users import UserRole, UserStatus, users
from .models.tags import tags, study_tags
from .models.api_keys import api_keys

__all__ = [
"users",
Expand All @@ -27,4 +28,5 @@
"comp_pipeline",
"tags",
"study_tags",
"api_keys",
]
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#
# $ make devenv
#
pylint
black
pip-tools
rope
Expand Down
9 changes: 5 additions & 4 deletions scripts/common.Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,12 @@ info: ## displays basic info
@echo ' NOW_TIMESTAMP : ${NOW_TIMESTAMP}'
@echo ' VCS_URL : ${VCS_URL}'
@echo ' VCS_REF : ${VCS_REF}'
# installed
# installed in .venv
@pip list
# version
@cat setup.py | grep name=
@cat setup.py | grep version=
# package
-@echo ' name : ' $(shell python ${CURDIR}/setup.py --name)
-@echo ' version : ' $(shell python ${CURDIR}/setup.py --version)



.PHONY: autoformat
Expand Down
2 changes: 1 addition & 1 deletion services/api-gateway/.cookiecutterrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ default_context:
project_name: 'Public API Gateway'
project_short_description: "Platform's API Gateway for external clients"
project_slug: 'api-gateway'
version: '0.1.0'
version: '0.1.1'
year: '2020'
13 changes: 13 additions & 0 deletions services/api-gateway/.env-devel
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# Environment variables used to configure this service
#

# SEE services/api-gateway/src/simcore_service_api_gateway/auth_security.py
SECRET_KEY=d0d0397de2c85ad26ffd4a0f9643dfe3a0ca3937f99cf3c2e174e11b5ef79880

# SEE services/api-gateway/src/simcore_service_api_gateway/settings.py
LOGLEVEL=DEBUG

POSTGRES_USER=test
POSTGRES_PASSWORD=test
POSTGRES_DB=test
20 changes: 12 additions & 8 deletions services/api-gateway/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ export APP_VERSION = $(shell cat VERSION)
reqs: ## compiles pip requirements (.in -> .txt)
@$(MAKE) --directory requirements reqs


.PHONY: install-dev install-prod install-ci
install-dev install-prod install-ci: _check-venv-active ## install app in development/production or CI mode
install-dev install-prod install-ci: _check_venv_active ## install app in development/production or CI mode
# installing in $(subst install-,,$@) mode
pip-sync requirements/$(subst install-,,$@).txt

Expand All @@ -34,23 +35,26 @@ tests-integration: ## runs integration tests against local+production images


.PHONY: run-devel down
run-devel: down ## runs app with pg fixture for development
# starting pg database ...
docker-compose -f $(CURDIR)/tests/unit/with_dbs/docker-compose.yml up --detach
# starting service
export SECRET_KEY="d0d0397de2c85ad26ffd4a0f9643dfe3a0ca3937f99cf3c2e174e11b5ef79880"; \
run-devel: .env-devel down ## runs app on host with pg fixture for development
# running current app
export $(shell grep -v '^#' $< | xargs -d '\n'); \
docker-compose -f $(CURDIR)/tests/utils/docker-compose.yml up --detach; \
uvicorn simcore_service_api_gateway.main:the_app --reload --port=8001 --host=0.0.0.0
# stop

down: ## stops pg fixture
docker-compose -f $(CURDIR)/tests/unit/with_dbs/docker-compose.yml down
# stopping extra services
-@docker-compose -f $(CURDIR)/tests/utils/docker-compose.yml down
# killing any process using port 8001
-@fuser --kill --verbose --namespace tcp 8001


.PHONY: build
build: ## builds docker image (using main services/docker-compose-build.yml)
@$(MAKE) --directory ${REPO_BASE_DIR} target=${APP_NAME} $@


.PHONY: replay
# TODO: replay shall point to online cookiecutter
replay: .cookiecutterrc ## re-applies cookiecutter
# Replaying /home/crespo/devp/osparc-simcore/services/api-gateway/../../../cookiecutter-simcore-py-fastapi ...
@cookiecutter --no-input --overwrite-if-exists \
Expand Down
7 changes: 7 additions & 0 deletions services/api-gateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,10 @@ Platform's API Gateway for external clients
[image-version]https://images.microbadger.com/badges/version/itisfoundation/api-gateway.svg
[image-commit]:https://images.microbadger.com/badges/commit/itisfoundation/api-gateway.svg
<!------------------------->



## References

- [Design patterns for modern web APIs](https://blog.feathersjs.com/design-patterns-for-modern-web-apis-1f046635215) by D. Luecke
- [API Design Guide](https://cloud.google.com/apis/design/) by Google Cloud
2 changes: 1 addition & 1 deletion services/api-gateway/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0
0.1.1
3 changes: 3 additions & 0 deletions services/api-gateway/requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@

# installs current package
-e .

# common dev-tools as well
-r ../../../requirements.txt
2 changes: 1 addition & 1 deletion services/api-gateway/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.1.0
current_version = 0.1.1
commit = True
tag = True

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
major, minor, patch = __version__.split(".")

api_version = __version__
api_version_prefix: str = f"v{major}"
api_vtag: str = f"v{major}"
Loading