Skip to content
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

feat: api_key and basic_auth security scheme support #134

Merged
Merged
Changes from all commits
Commits
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: 4 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -29,8 +29,10 @@ jobs:
node --version

yarn test:unit
- name: Collect coverage
run: ./node_modules/codecov/bin/codecov
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}

E2E:
runs-on: ubuntu-latest
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -166,14 +166,18 @@ Serverless Framework plugin to manage APIs on [WSO2 API Manager](https://wso2.co
> | `backend.jms.destination` | Your JMS Destination (queue or topic name) | `MY.BACKEND.TOPIC` |
> | `backend.jms.parameters` | List of JMS connection parameters to be used in `key`:`value` form as described [here](https://axis.apache.org/axis2/java/transports/jms.html). | `transport.jms.ConnectionFactory: 'My-ConnectionFactory'` |
> | `backend.endpointType` | Optional, defaults to `http`. If you are using a non standard WSO2 extension, you might want to be able to override this. | `http`, `jms`, `lambda` |
> | `securityScheme` | Optional, defaults to `oath2`. Supports `mutualssl` and `oauth2`. <br>. |
> | `securityScheme` | Optional, defaults to `oath2`. Supports `mutualssl`, `oauth2`, `apiKey` and `basicAuth`. <br>. |
> | `securityScheme.mutualssl` | Requires `securityScheme.mutualssl.enabled` and `securityScheme.mutualssl.clientCert` to be defined. <br>. |
> | `securityScheme.mutualssl.clientCert` | Required with mutualssl, your client certificate chain in PEM (base64) format. <br><br> It supports: <br> a. **File system** - Path must be relative to where `serverless.yml` is located. <br> b. **AWS Certificate ARN** <br> c. **AWS CloudFormation Export** - Exported value must contain a valid AWS Certificate ARN. | `file://certs/backend.cer` <br> (or) <br> `arn:aws:acm:..` <br> (or) <br> `!ImportValue xx` |
> | `securityScheme.mutualssl.enabled` | Required with `securityScheme.mutualssl`. Expects `true` or `false` <br>. |
> | `securityScheme.oauth2` | Requires `securityScheme.oauth2.enabled` to be defined. <br>. |
> | `securityScheme.oauth2.enabled` | Required with `securityScheme.oauth2`. Expects `true` or `false` <br>.
> | `securityScheme.oauth2.mandatory` | Optional with `securityScheme.oauth2`. Expects `true` or `false` <br>.
> | `securityScheme.oauth2.keyManager` | Optional with `securityScheme.oauth2`. Array of keys to be used by API
> | `securityScheme.apiKey` | Requires `securityScheme.apiKey.enabled` to be defined. <br>. |
> | `securityScheme.apiKey.enabled` | Required with `securityScheme.apiKey`. Expects `true` or `false` <br>.
> | `securityScheme.basicAuth` | Requires `securityScheme.basicAuth.enabled` to be defined. <br>. |
> | `securityScheme.basicAuth.enabled` | Required with `securityScheme.basicAuth`. Expects `true` or `false` <br>.
> | `mediationPolicies` | Optional, your choice of mediation policies (or) sequences. They can manipulate input/output/fault messages as described [here](https://docs.wso2.com/display/AM260/Adding+Mediation+Extensions). | |
> | `mediationPolicies.in` | Input mediation policy, it manipulates the request going to your backend. | `log_in_message` |
> | `mediationPolicies.out` | Output mediation policy, it manipulates the response going back to your API consumer. | `json_validator` |
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "serverless-wso2-apim",
"version": "0.7.1",
"version": "0.7.2",
"description": "Serverless Framework plugin for WSO2 API Manager",
"main": "src/index.js",
"scripts": {
11 changes: 8 additions & 3 deletions src/3.2.0/wso2apim.js
Original file line number Diff line number Diff line change
@@ -201,11 +201,16 @@ async function constructAPIDef(user, gatewayEnv, apiDef, apiId) {
securityScheme.push('mutualssl_mandatory');
}
if (apiDef.securityScheme && apiDef.securityScheme.oauth2 && apiDef.securityScheme.oauth2.enabled === true) {
securityScheme.push("oauth2");
securityScheme.push('oauth2');
if (apiDef.securityScheme.oauth2.mandatory) {
securityScheme.push("oauth_basic_auth_api_key_mandatory");
securityScheme.push('oauth_basic_auth_api_key_mandatory');
}

}
if (apiDef.securityScheme && apiDef.securityScheme.apiKey && apiDef.securityScheme.apiKey.enabled === true) {
securityScheme.push('api_key');
}
if (apiDef.securityScheme && apiDef.securityScheme.basicAuth && apiDef.securityScheme.basicAuth.enabled === true) {
securityScheme.push('basic_auth');
}
const wso2ApiDefinition = {
id: apiId,
59 changes: 58 additions & 1 deletion src/3.2.0/wso2apim.spec.js
Original file line number Diff line number Diff line change
@@ -59,7 +59,9 @@ const wso2APIM = {
enabled: true,
clientCert: 'file://xxx.cer'
},
oauth2: { enabled: true, keyManager: ["Resident Key Manager"] }
oauth2: { enabled: true, keyManager: ["Resident Key Manager"] },
apiKey: { enabled: true },
basicAuth: { enabled: true }
},
tags: [ 'awesomeness', 'myawesomeapi'],
maxTps: 999,
@@ -783,4 +785,59 @@ describe('wso2apim-3.2.0', () => {
});
});

describe('security schemas', () => {
it('all provided', async () => {
const apiDef = await constructAPIDef(
wso2APIM.user,
wso2APIM.gatewayEnv,
wso2APIM.apidefs[0]
);

expect(apiDef.securityScheme).toEqual(['mutualssl', 'mutualssl_mandatory', 'oauth2', 'api_key', 'basic_auth']);
});

it('apiKey provided', async () => {
const config = {
...wso2APIM,
apidefs: [
{
...wso2APIM.apidefs[0],
securityScheme: {
apiKey: { enabled: true },
}
},
],
};

const apiDef = await constructAPIDef(
config.user,
config.gatewayEnv,
config.apidefs[0]
);

expect(apiDef.securityScheme).toEqual(['api_key']);
});

it('basicAuth provided', async () => {
const config = {
...wso2APIM,
apidefs: [
{
...wso2APIM.apidefs[0],
securityScheme: {
basicAuth: { enabled: true },
}
},
],
};

const apiDef = await constructAPIDef(
config.user,
config.gatewayEnv,
config.apidefs[0]
);

expect(apiDef.securityScheme).toEqual(['basic_auth']);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
service: serverless-wso2-apim
provider:
name: aws
stackName: ${env:STACK_NAME}
deploymentBucket:
name: ${env:TEST_ID_NORMALIZED}
plugins:
- serverless-localstack
- serverless-deployment-bucket
- "../../../../../src"

#⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇ Modify the configuration below to suit your test case.
#⬇⬇⬇ START HERE ⬇⬇⬇⬇ Help: https://github.com/ramgrandhi/serverless-wso2-apim#configuration-reference
#⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇ For a full list of env vars that you can use, refer `src/__tests__/e2e/e2e.test.js`
custom:
wso2apim:
enabled: true
host: ${env:WSO2_HOST}
port: ${env:WSO2_PORT}
user: ${env:WSO2_USER}
pass: ${env:WSO2_PASS}
gatewayEnv: ${env:WSO2_ENV}
apidefs:
- name: ${env:TEST_ID}-1
description: ${env:TEST_ID}-1
rootContext: /${env:TEST_ID}-1
version: "v1"
visibility: "PRIVATE"
securityScheme:
apiKey:
enabled: true
basicAuth:
enabled: true
backend:
http:
baseUrl: "https://baseUrl"
maxTps: 10
tags:
- ${env:TEST_ID}-1
swaggerSpec:
swagger: "2.0"
info:
title: ${env:TEST_ID}-1
version: "v1"
contact:
name: ${env:TEST_ID}-1
email: ${env:TEST_ID}-1
paths:
/*:
post:
responses:
"201":
description: Created
x-auth-type: "None"
# - name: ${env:TEST_ID}-2
# description: ${env:TEST_ID}-2
# rootContext: /${env:TEST_ID}-2
# version: "1"
# visibility: "PUBLIC"
# backend:
# http:
# baseUrl: "https://baseUrl"
# maxTps: 10
# tags:
# - ${env:TEST_ID}-2
# swaggerSpec:
# openapi: 3.0.0
# info:
# title: ${env:TEST_ID}-2
# version: "1"
# contact:
# name: ${env:TEST_ID}-2
# email: ${env:TEST_ID}-2
# paths:
# /*:
# post:
# responses:
# "201":
# description: Created
# x-auth-type: "None"

# Optionally, add your other AWS provider-specific resources below.
# Make sure there is at least one resource listed below, otherwise stack deployment would fail.
resources:
Resources:
Topic:
Type: AWS::SNS::Topic
4 changes: 3 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -240,7 +240,9 @@ class Serverless_WSO2_APIM {
((semver.lt(this.cache.wso2apimVersion, '3.2.0') && (wso2APIM.apidefs.every(def => typeof def.securityScheme === 'undefined'))) ||
(semver.gte(this.cache.wso2apimVersion, '3.2.0') && (wso2APIM.apidefs.every(def => typeof def.securityScheme === 'undefined' ||
(def.securityScheme && def.securityScheme.mutualssl && def.securityScheme.mutualssl.enabled && def.securityScheme.mutualssl.clientCert) ||
(def.securityScheme && def.securityScheme.oauth2 && typeof def.securityScheme.oauth2.enabled === 'boolean'))
(def.securityScheme && def.securityScheme.oauth2 && typeof def.securityScheme.oauth2.enabled === 'boolean') ||
(def.securityScheme && def.securityScheme.apiKey && typeof def.securityScheme.apiKey.enabled === 'boolean') ||
(def.securityScheme && def.securityScheme.basicAuth && typeof def.securityScheme.basicAuth.enabled === 'boolean'))
)))
];
const messagesArraySpecific = [