Skip to content

External IdP validation feature for API Backends #401

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

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ba64ff2
The configuration file was modified to include two additional fields …
anmunoz Oct 26, 2017
6c1280e
In this file, I include two more nginx server variables for checking …
anmunoz Oct 26, 2017
254988b
This file was modified for including the token validation, the method…
anmunoz Oct 26, 2017
0554070
This function usually is used for inverting the roles table, it was m…
anmunoz Oct 26, 2017
07e2aa5
This function allows to connect with the Pep Proxy service for checki…
anmunoz Oct 26, 2017
bbf9f0b
The user_store function was modified for including the token validati…
anmunoz Oct 26, 2017
f0839eb
Merge pull request #1 from ging/token_validation
anmunoz Oct 26, 2017
0e86c30
Revert "New feature for OAuth2 Token Validation using Fiware Wilma PE…
anmunoz Nov 7, 2017
8f57775
Merge pull request #2 from ging/revert-1-token_validation
anmunoz Nov 7, 2017
a0166f4
The configuration file was modified to include one additional field …
anmunoz Nov 13, 2017
99fb1b0
In this file, I include two more nginx server variables for checking…
anmunoz Nov 13, 2017
1ead407
This function usually is used for inverting the roles table, it was …
anmunoz Nov 13, 2017
ae7143b
This function allows to connect with an IdP service (Google, Facebook…
anmunoz Nov 13, 2017
0eacb11
This file was modified for including the token validation, the method…
anmunoz Nov 13, 2017
ac81453
The user_store function was modified for including the token validat…
anmunoz Nov 13, 2017
739c99e
Correcting validation mistake for allowing access to the api backend …
anmunoz Nov 14, 2017
80bb4fb
Fix on Vagrantfile for synchronizing files in admin-ui
agordillo Feb 13, 2018
58cc570
Add external idps field to apis form
agordillo Feb 13, 2018
79c4a43
Add require_idp field to apis (client and server sides)
agordillo Feb 13, 2018
cecb00d
Adding the web interface fields for external idp validation for api b…
anmunoz Feb 13, 2018
1e561c7
Fixing some code for integrating the external IdP validation with the…
anmunoz Feb 14, 2018
0574328
Pre-merge
anmunoz Feb 14, 2018
93fa85c
Merge branch 'master' of https://github.com/ging/api-umbrella
anmunoz Feb 14, 2018
0ee3b3d
Adding documentation for using external IdP validation
anmunoz Feb 14, 2018
fb48514
Correcting the documentation
anmunoz Feb 14, 2018
a1d583c
documentation update
anmunoz Feb 26, 2018
d52a594
Merge branch 'master' into master
anmunoz Mar 6, 2018
678b1d5
Pre-merge for validating trusted applications
anmunoz Mar 19, 2018
1f108d9
Merge branch 'master' of https://github.com/ging/api-umbrella
anmunoz Mar 19, 2018
cf69008
adding new type of requests for FIWARE IDP, now is possible to work i…
anmunoz Oct 8, 2018
ee9b3b8
working with default IDP declared in he config.yml
anmunoz Oct 8, 2018
b58c352
correction config.yml
anmunoz Oct 8, 2018
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
6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ API Umbrella is an open source API management platform for exposing web service

Binary packages are available for [download](https://apiumbrella.io/install/). Follow the quick setup instructions on the download page to begin running API Umbrella.

## Additional Features

In this repo is hosted one additional feature of API-Umbrella for providing validation using external IdP's.
The documentation about how to use is available here: [Documentation](./docs/idp-doc.md)

## Getting Started

Once you have API Umbrella up and running, there are a variety of things you can do to start using the platform. For a quick tutorial, see [getting started](https://api-umbrella.readthedocs.org/en/latest/getting-started.html).
Expand Down
1 change: 1 addition & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Vagrant.configure("2") do |config|
end

config.vm.synced_folder "src/api-umbrella/admin-ui", "/vagrant-admin-ui",
:nfs => options[:nfs],
:type => "rsync",
:rsync__verbose => true,
:rsync__exclude => [
Expand Down
Empty file modified bin/api-umbrella
100755 → 100644
Empty file.
Empty file modified bin/api-umbrella-cli
100755 → 100644
Empty file.
Empty file modified bin/api-umbrella-exec
100755 → 100644
Empty file.
Empty file modified bin/api-umbrella-geoip-auto-updater
100755 → 100644
Empty file.
Empty file modified bin/api-umbrella-nginx-reloader
100755 → 100644
Empty file.
Empty file modified bin/docker-compose/make
100755 → 100644
Empty file.
Empty file modified bin/docker-compose/rake
100755 → 100644
Empty file.
Empty file modified build/package/build_package
100755 → 100644
Empty file.
Empty file modified build/package/docker_run
100755 → 100644
Empty file.
Empty file modified build/package/docker_script
100755 → 100644
Empty file.
Empty file modified build/package/files/etc/init.d/api-umbrella
100755 → 100644
Empty file.
Empty file modified build/package/parse_version
100755 → 100644
Empty file.
Empty file modified build/package/publish
100755 → 100644
Empty file.
Empty file modified build/package/scripts/after-install
100755 → 100644
Empty file.
Empty file modified build/package/scripts/after-remove
100755 → 100644
Empty file.
Empty file modified build/package/scripts/before-remove
100755 → 100644
Empty file.
Empty file modified build/package/verify/docker_run
100755 → 100644
Empty file.
Empty file modified build/package/verify/docker_script
100755 → 100644
Empty file.
Empty file modified build/package/verify/download_previous_packages
100755 → 100644
Empty file.
Empty file modified build/scripts/distclean
100755 → 100644
Empty file.
Empty file modified build/scripts/download_cmake
100755 → 100644
Empty file.
Empty file modified build/scripts/install_build_dependencies
100755 → 100644
Empty file.
28 changes: 21 additions & 7 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,17 @@ gatekeeper:
- header
- getParam
- basicAuthUsername
api_key_cache: true
api_key_cache: false
positive_ttl: 120
negative_ttl: 60
idp_providers:
- fiware-oauth2
- github-oauth2
- facebook-oauth2
- google-oauth2
default_idp:
backend_name: fiware-oauth2
host: http://138.4.7.8:8000
trafficserver:
host: 127.0.0.1
port: 14009
Expand Down Expand Up @@ -283,12 +293,12 @@ apiSettings:
message: The requested URL was not found on this server.
api_key_missing:
status_code: 403
code: API_KEY_MISSING
message: No api_key was supplied. Get one at {{signup_url}}
code: API_KEY_OR_TOKEN_MISSING
message: No api_key or token was supplied. Get one at {{signup_url}}
api_key_invalid:
status_code: 403
code: API_KEY_INVALID
message: An invalid api_key was supplied. Get one at {{signup_url}}
code: API_KEY_OR_TOKEN_INVALID
message: An invalid api_key or token was supplied. Get one at {{signup_url}}
api_key_disabled:
status_code: 403
code: API_KEY_DISABLED
Expand All @@ -299,8 +309,12 @@ apiSettings:
message: The api_key supplied has not been verified yet. Please check your e-mail to verify the API key. Contact us at {{contact_url}} for assistance
api_key_unauthorized:
status_code: 403
code: API_KEY_UNAUTHORIZED
message: The api_key supplied is not authorized to access the given service. Contact us at {{contact_url}} for assistance
code: API_KEY_OR_TOKEN_UNAUTHORIZED
message: The api_key or token supplied is not authorized to access the given service. Contact us at {{contact_url}} for assistance
not_trusted_app:
status_code: 403
code: NOT_TRUSTED_APPLICATION
message: The application trying to access the API_BACKEND is not trusted
over_rate_limit:
status_code: 429
code: OVER_RATE_LIMIT
Expand Down
Empty file modified configure
100755 → 100644
Empty file.
23 changes: 23 additions & 0 deletions docker-ging/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM centos:centos6

ENV API_UMBRELLA_VERSION 0.14.4-1~centos

# Install API Umbrella
RUN yum -y update; yum clean all
RUN yum -y install git
RUN groupadd -r api-umbrella && \
useradd -r -g api-umbrella -s /sbin/nologin -d /opt/api-umbrella -c "API Umbrella user" api-umbrella
RUN git clone https://github.com/ging/api-umbrella.git
RUN chmod 775 -R ./api-umbrella
RUN cd ./api-umbrella && ./build/scripts/install_build_dependencies && ./configure && make && make install


# Define mountable directories
VOLUME ["/etc/api-umbrella", "/opt/api-umbrella/var/db", "/opt/api-umbrella/var/log"]

# Expose HTTP and HTTPS ports
EXPOSE 80 443

# Run the API Umbrella service
CMD ["api-umbrella", "run"]

Empty file modified docker/dev/docker-start
100755 → 100644
Empty file.
221 changes: 221 additions & 0 deletions docs/idp-doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
## External IdP Validation

This new feature allows to the API-umbrella users
the possibility of make request to a registered API
backend, using an API key or an OAuth2 token.
If the user uses a token in the request, this token is verified using an external IdP, once the token is validated the user information is retrieved and redirect to the API backend following the usual workflow.
The list of IdP's
included in this development are:

* Fiware
* Google
* Facebook
* GitHub

Hence, after the inclusion of this feature,
the gatekeeper architecture is modified
as is showed in the next figure:

![API-Umbrella architecture](./images/idp-arch.png)

## Getting Started

### Installation
For using API-Umbrella with External IdP validation, you have to clone
this repo and install API-Umbrella from source code. The instructions fordoing this are:

Note: This installation was tested with centos 6 and 7 with other Linux
distribution should work too but, is recommended to use centos

First, clone the repo and install:

```
$ git clone https://github.com/ging/api-umbrella.git
$ chmod 775 -R ./api-umbrella
$ cd api-umbrella
$ sudo ./build/scripts/install_build_dependencies
$ ./configure
$ make
$ sudo make install
```
This process could take some minutes while it download and install the dependencies.

Second, start API-Umbrella

```
sudo /etc/init.d/api-umbrella start
```
### Docker API-Umbrella

Also, you have the option of use a docker container instead of install
API-Umbrella. The instructions for creating and running the docker
container with this version of API umbrella are:

You can run directly the container pulling the image from the docker hub:

```
$ docker run -d --name=api-umbrella -p 80:80 -p 443:443 martel/api-umbrella
```

Or build the API-Umbrella image and run the container:

```
$ git clone https://github.com/ging/api-umbrella.git
$ cd api-umbrella/docker-ging
$ docker build -t umbrella:0.14.4 .
```

Once you have your api-umbrella image, you can run the container and use it

```
$ docker run -d --name=api-umbrella -p 80:80 -p 443:443 umbrella:0.14.4
```

### Admin and User guide

At this point, you can perform the same operations described in
[getting started](https://api-umbrella.readthedocs.org/en/latest/getting-started.html). but Also
in this section is included the guide of how to create API backends for processing
the requests using Oauth2 token and external IdP's

#### Registering and API-Backend uding API REST

The procedure of how you can create a request using an REST call is available in the official documentation but,
for using the external validation feature you need to include in you JSON body request the field ** require_idp:<IdP-value> ** where IdP value could be one of this: fiware-oauth2, google-oauth2, facebook-oauth2, github-oauth2.

An request example for registring a API-backend with a generic parameters is:

```
curl -k -X POST "https://<your-api-umbrella-hostaname>/api-umbrella/v1/apis" -H "X-Api-Key: <your-API-KEY>" -H "X-Admin-Auth-Token: <your-admin-auth-token>" -H "Accept: application/json" -H "Content-Type: application/json" -d @- <<EOF
{
"api": {
"name": "distance FIWARE REST",
"sort_order": 100000,
"backend_protocol": "http",
"frontend_host": "127.0.0.1",
"backend_host": "maps.googleapis.com",
"servers": [
{
"host": "maps.googleapis.com",
"port": 80
}
],
"url_matches": [
{
"frontend_prefix": "/distance2/",
"backend_prefix": "/"
}
],
"balance_algorithm": "least_conn",
"settings": {
"require_https":"required_return_error",
"require_idp": "fiware-oauth2",
"disable_api_key":"false",
"api_key_verification_level":"none",
"rate_limit_mode":"unlimited",
"error_templates": {},
"error_data": {}
}
}
}
EOF
```

In the current example we create an API-BAckend that use the google maps library for retreaving the distance between two points. This backend was configure for making the token validation with the Fiware external IdP.

The output, should return the JSON with the parameters that you sent

#### Registering and API-Backend
The next figures show the Web UI for creating an API backend. You need to
fill the fields for registering you API but, for choosing
the external IdP in order to validate the user's token you have to go to
the **Global request setting** dropdown, in that part of the page, you have to choose
between the available IdP's in the option **External Identity Provider**
. Once you were selected the IdP, you need to save the backend and publish it

![API-backend creation](./images/create-backend.png)
![API-backend creation](./images/create-backend-ex.png)

#### Making requests to your API's

For making requests to your API's with the external IdP validation
you need to send the Oauth2 user token by param or header.

Sending the token by param:
```
curl -k "https://<your-api-umbrella-hostname>/<your-api-query>?token=<your-token>"

```
An example of using the google maps API backend registered in API-Umbrella:

```
curl -k "https://127.0.0.1/distance1/maps/api/distancematrix/json?units=imperial&origins=Washington,DC&destinations=New+York+City,NY&token=XXXXXXXXXX"
```
Output:
```
{
"destination_addresses" : [ "New York, NY, USA" ],
"origin_addresses" : [ "Washington, DC, USA" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "225 mi",
"value" : 361940
},
"duration" : {
"text" : "3 hours 51 mins",
"value" : 13839
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}

```

For sending the token via header:

```
curl -k -H "X-Auth-Token:<your-token>" "https://<your-api-umbrella-hostname>/<your-query>"
```

An example using the same API backend of google maps.

```
curl -k -H "X-Auth-Token:XXXXXX" "https://127.0.0.1/distance/maps/api/distancematrix/json?units=imperial&origins=Washington,DC&destinations=New+York+City,NY"
```
Output:
```
{
"destination_addresses" : [ "New York, NY, USA" ],
"origin_addresses" : [ "Washington, DC, USA" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "225 mi",
"value" : 361940
},
"duration" : {
"text" : "3 hours 51 mins",
"value" : 13839
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}

```
For any additional questions or support please send an email to:

* <[email protected]>

Binary file added docs/images/create-backend-ex.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/create-backend.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/idp-arch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified scripts/fix-log-geoip/fix
100755 → 100644
Empty file.
Empty file modified scripts/generate_user_agent_data
100755 → 100644
Empty file.
Empty file modified scripts/import_access_logs/import
100755 → 100644
Empty file.
Empty file modified scripts/replay_logs
100755 → 100644
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@ export default Component.extend({
{ id: false, name: I18n.t('admin.api.settings.disable_api_key_options.required') },
{ id: true, name: I18n.t('admin.api.settings.disable_api_key_options.disabled') },
];

this.requireIdpOptions: [
{ id: null, name: I18n.t('admin.api.settings.require_idp_options.inherit') },
{ id: 'none', name: I18n.t('admin.api.settings.require_idp_options.none') },
{ id: 'fiware-oauth2', name: "FIWARE" },
{ id: 'github-oauth2', name: "GitHub" },
{ id: 'facebook-oauth2', name: "Facebook" },
{ id: 'google-oauth2', name: "Google" },
];
this.apiKeyVerificationLevelOptions = [
{ id: null, name: I18n.t('admin.api.settings.api_key_verification_level_options.inherit') },
{ id: 'none', name: I18n.t('admin.api.settings.api_key_verification_level_options.none') },
{ id: 'transition_email', name: I18n.t('admin.api.settings.api_key_verification_level_options.transition_email') },
{ id: 'required_email', name: I18n.t('admin.api.settings.api_key_verification_level_options.required_email') },
];

this.passApiKeyOptions = [
{ id: 'header', name: I18n.t('admin.api.settings.pass_api_key_header') },
{ id: 'param', name: I18n.t('admin.api.settings.pass_api_key_param') },
Expand Down
1 change: 1 addition & 0 deletions src/api-umbrella/admin-ui/app/models/api/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default DS.Model.extend({
requireHttps: DS.attr(),
disableApiKey: DS.attr(),
apiKeyVerificationLevel: DS.attr(),
requireIdp: DS.attr(),
requiredRoles: DS.attr(),
requiredRolesOverride: DS.attr(),
allowedIps: DS.attr(),
Expand Down
4 changes: 3 additions & 1 deletion src/api-umbrella/admin-ui/app/routes/apis/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { hash } from 'rsvp';
export default Base.extend(Confirmation, UncachedModel, {
// Return a promise for loading multiple models all together.
fetchModels(record) {
return hash({

//TODO: add external IDPs config here
return Ember.RSVP.hash({
record: record,
roleOptions: this.get('store').findAll('api-user-role', { reload: true }),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{{f.select-field "requireHttps" label=(t "admin.api.settings.require_https") tooltip=(t "admin.api.settings.require_https_tooltip_markdown") options=requireHttpsOptions}}
{{f.select-field "disableApiKey" label=(t "admin.api.settings.disable_api_key") options=disableApiKeyOptions}}
{{f.select-field "apiKeyVerificationLevel" label=(t "admin.api.settings.api_key_verification_level") options=apiKeyVerificationLevelOptions}}
{{f.select-field "requireIdp" label=(t "admin.api.settings.require_idp") options=requireIdpOptions}}
{{f.selectize-field "requiredRolesString" label=(t "admin.api.settings.required_roles") tooltip=(t "admin.api.settings.required_roles_tooltip_markdown") options=roleOptions}}
{{#if isSubSettings}}
{{f.checkbox-field "requiredRolesOverride" label=(t "admin.api.settings.required_roles_override") tooltip=(t "admin.api.settings.required_roles_override_tooltip_markdown")}}
Expand Down
4 changes: 3 additions & 1 deletion src/api-umbrella/proxy/hooks/rewrite.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ wait_for_setup()
-- ngx.var lookups are apparently somewhat expensive.
ngx.ctx.args = ngx_var.args
ngx.ctx.arg_api_key = ngx_var.arg_api_key
ngx.ctx.arg_token = ngx_var.arg_token
if(config["router"]["match_x_forwarded_host"]) then
ngx.ctx.host = ngx_var.http_x_forwarded_host or ngx_var.http_host or ngx_var.host
else
ngx.ctx.host = ngx_var.http_host or ngx_var.host
end
ngx.ctx.host_normalized = host_normalize(ngx.ctx.host)
ngx.ctx.http_x_api_key = ngx_var.http_x_api_key
ngx.ctx.http_x_auth_token = ngx_var.http_x_auth_token
ngx.ctx.port = ngx_var.real_port
ngx.ctx.protocol = ngx_var.real_scheme
ngx.ctx.remote_addr = ngx_var.remote_addr
Expand Down Expand Up @@ -72,4 +74,4 @@ else
else
error_handler(api_err)
end
end
end
Loading