Skip to content

Commit

Permalink
Merge pull request #174 from koopjs/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
mfgumban authored Jul 15, 2020
2 parents 9537d86 + d64a870 commit 38c0674
Show file tree
Hide file tree
Showing 38 changed files with 1,248 additions and 65 deletions.
108 changes: 77 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,47 +61,66 @@ We could only get Esri Insights to work with HTTP requests on port 80 and HTTPS

The project uses the node [config](https://www.npmjs.com/package/config) package to manage configurations. Update the necessary `config/FILENAME.json` file. You can use the `config/default.json` as a starting point. To make use of your configuration execute `export NODE_ENV=<environment>` before you run `node server.js`.

### Test Settings
### Authentication

The test project uses the above node settings for the node server and [gradle properties plugin](https://github.com/stevesaliman/gradle-properties-plugin) to manage environment properties for gradle. Create a `/test/gradle-<environment>.properties` file to specify your environment settings that match your `/config/<environment>.json`.
The project supports the following authentication strategies:

The following properties can be overriden:
- None (Default)
- MarkLogic
- File-based

```
mlAppName=<the name of the connector>
mlHost=<host>
mlRestPort=<port>
koopMlUsername=<username>
koopMlPassword=<password>
# Koop server setttings
# Port the feature service will service HTTP requests on
koopPort=<http port>
# Whether or not to enable an HTTPS server as well
koopSSLEnabled=<true|false>
# Port the feature service will service HTTPS requests on
koopSSLPort=<https port>
# The SSL certificate to user for the HTTPS server
koopSSLCert=<path to certificate pem file>
# The SSL certificate key to user for the HTTPS server
koopSSLKey=<path to the certificate public key file>
```
#### No Authentication

Add the `-PenvironmentName=<environment>` argument when running gradle to utilize your configuration, you can copy the `/test/gradle.properties` default file as a starting point.
All Koop services will be publicly accessible. Koop will still need valid MarkLogic credentials to communicate with MarkLogic. See `config/default.json` for an example.

---
#### MarkLogic Authentication

### Tested Configuration
This uses a _direct authentication_ pattern similar to [Koop-Auth-Direct-File](https://github.com/koopjs/koop-auth-direct-file), with MarkLogic being responsible for authenticating user credentials. The credentials supplied must match a valid MarkLogic server user account.

To setup, add an `auth` section to your `config/FILENAME.json`, for example:

```json
"auth": {
"plugin": "auth-marklogic-digest-basic",
"enabled": true,
"options": {
"secret": "7072c433-a4e7-4749-86f3-849a3ed0ee95",
"tokenExpirationMinutes": 60
}
}
```
NPM 6.4.1
Node 10.2.1
MarkLogic 9.0-10
MarkLogic Geo Data Services 1.1.0

| Option | Description | Value | Default value |
|------------------------|-----------------------------------------------|-----------------------------|---------------------|
| secret | Used to verify JSON web tokens | string | auto-generated UUID |
| tokenExpirationMinutes | The validity of tokens in minutes | Number | 60 |

#### File-based Authentication

This uses the [Koop-Auth-Direct-File](https://github.com/koopjs/koop-auth-direct-file) module for authentication. Check out its [official project page](https://github.com/koopjs/koop-auth-direct-file) for more information.

To setup, add an `auth` section to your `config/FILENAME.json`, for example:

```json
"auth": {
"plugin": "auth-direct-file",
"enabled": true,
"options": {
"secret": "7072c433-a4e7-4749-86f3-849a3ed0ee95",
"tokenExpirationMinutes": 60,
"identityStore": "tests/user-store.json",
"useHttp": true
}
}
```

| Option | Description | Value | Default value |
|------------------------|-----------------------------------------------|-----------------------------|---------------------|
| secret | Used to verify JSON web tokens | string | auto-generated UUID |
| tokenExpirationMinutes | The validity of tokens in minutes | Number | 60 |
| identityStore | Path to JSON file containing list of users | string | none |
| useHttp | Allow HTTP for token services | boolean | false |

## Running the Connector

The connector uses Koop as the client-facing HTTP/S service. Koop utilizes a Node.js Express server to handle feature service requests.
Expand Down Expand Up @@ -148,3 +167,30 @@ The [MarkLogic ArcGIS Pro add-in](https://github.com/marklogic-community/marklog
```

For security purposes, the *service proxy* is **disabled** by default.

## Tests

### Setup Test Environment

1. Ensure you have a local MarkLogic server running.
2. Go to `tests/ml` directory.
3. Run `./gradlew mlDeploy` to deploy the test database.

### Run Tests

1. Go to the project root directory.
2. Run `./run-tests.sh` to run all tests.

### Run Individual Tests

The tests are organized in several test suites:

1. test:default - no authentication tests
2. test:auth-ml - MarkLogic authentication tests
3. test:auth-direct-file - Direct File authentication tests

Use `npm run` to run them individually, for example:

```bash
npm run test:auth-ml
```
31 changes: 31 additions & 0 deletions config/test-auth-direct-file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"logger": {
"level": "debug"
},
"port": 9000,
"ssl": {
"enabled": false,
"port": 443,
"cert": "/ssl/cert.pem",
"key": "/ssl/key.pem"
},
"marklogic": {
"connection": {
"host": "localhost",
"port": 8097,
"user": "koop-marklogic-provider-test-dept-admin",
"password": "test",
"authType": "DIGEST"
}
},
"auth": {
"plugin": "auth-direct-file",
"enabled": true,
"options": {
"secret": "7072c433-a4e7-4749-86f3-849a3ed0ee95",
"identityStore": "tests/user-store.json",
"tokenExpirationMinutes": 60,
"useHttp": true
}
}
}
26 changes: 26 additions & 0 deletions config/test-auth-ml.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"logger": {
"level": "debug"
},
"port": 9000,
"ssl": {
"enabled": false,
"port": 443,
"cert": "/ssl/cert.pem",
"key": "/ssl/key.pem"
},
"marklogic": {
"connection": {
"host": "localhost",
"port": 8097
}
},
"auth": {
"plugin": "auth-marklogic-digest-basic",
"enabled": true,
"options": {
"secret": "7072c433-a4e7-4749-86f3-849a3ed0ee95",
"tokenExpirationMinutes": 60
}
}
}
21 changes: 21 additions & 0 deletions config/test-default.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"logger": {
"level": "debug"
},
"port": 9000,
"ssl": {
"enabled": false,
"port": 443,
"cert": "/ssl/cert.pem",
"key": "/ssl/key.pem"
},
"marklogic": {
"connection": {
"host": "localhost",
"port": 8097,
"user": "koop-marklogic-provider-test-dept-admin",
"password": "test",
"authType": "DIGEST"
}
}
}
21 changes: 0 additions & 21 deletions config/test.json

This file was deleted.

29 changes: 25 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
"name": "@koopjs/provider-marklogic",
"version": "1.1.1",
"version": "1.2.0",
"description": "A Marklogic provider for Koop",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"test:default": "cross-env NODE_ENV=test-default jest --silent --testTimeout=10000 --testNamePattern=test-default",
"test:auth-ml": "cross-env NODE_ENV=test-auth-ml jest --silent --testTimeout=10000 --testNamePattern=test-auth-ml",
"test:auth-direct-file": "cross-env NODE_ENV=test-auth-direct-file jest --silent --testTimeout=10000 --testNamePattern=test-auth-direct-file",
"start": "node server.js"
},
"dependencies": {
Expand All @@ -14,7 +16,11 @@
"koop": "3.11.0",
"featureserver": "2.17.0",
"@koopjs/auth-direct-file": "^2.0.0",
"marklogic": "^2.2.0"
"marklogic": "^2.2.0",
"jsonwebtoken": "^8.5.1",
"node-cache": "^5.1.0",
"yakaa": "^1.0.1",
"uuid": "^8.0.0"
},
"author": "MarkLogic",
"license": "Apache-2.0",
Expand All @@ -34,5 +40,20 @@
"data",
"big",
"data"
]
],
"devDependencies": {
"cross-env": "^7.0.2",
"jest": "^26.1.0",
"supertest": "^4.0.2"
},
"jest": {
"testEnvironment": "node",
"coveragePathIgnorePatterns": [
"/node_modules/"
],
"testPathIgnorePatterns": [
"/node_modules/",
"build"
]
}
}
5 changes: 5 additions & 0 deletions run-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

npm run test:default
npm run test:auth-ml
npm run test:auth-direct-file
31 changes: 27 additions & 4 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,43 @@ const express = require('express');
const http = require('http');
const proxy = require('./src/koop/proxy');
const Koop = require('koop');
//Important to require dbClientManager case sensitively as "dbClientManager"
//to get the node module cache to effectively make this be a singleton.
const dbClientManager = require('./src/koop/dbClientManager');
const koop = new Koop();

// Configure the auth plugin by executing its exported function with required args
if (config.auth && config.auth.enabled) {
let auth = null;
if (config.auth.plugin === 'auth-direct-file') {
auth = require('@koopjs/auth-direct-file')(config.auth.options.secret, config.auth.options.identityStore, config.auth.options);
} else {
throw new Error(`auth plugin ${config.auth.plugin} not recognized`);
dbClientManager.useStaticClient(true);
} else if (config.auth.plugin === 'auth-marklogic-digest-basic') {
auth = require("./src/koop/authMarkLogic")(config.auth.options);
} else if (config.auth.plugin) {
//if it's something we don't recognize, try to require it by plugin name and pass in the options object
//if this provider wants to use the static client, it will have to call dbClientManager.useStaticClient()
//itself in the exported function.
try {
auth = require(config.auth.plugin)(config.auth.options);
}
catch(err) {
throw new Error(`auth plugin ${config.auth.plugin} not recognized`);
}
}

if (auth) {
koop.register(auth);
}
}

log.info(`Using auth plugin ${config.auth.plugin}`);

} else {
//if there's no auth provider configured, we have to use a direct pre-authenticated db client
dbClientManager.useStaticClient(true);

log.info(`No auth plugin specified, relying on configured MarkLogic credentials`);
}
// install the Marklogic Provider
const provider = require('./src/koop');
koop.register(provider);
Expand All @@ -49,7 +70,7 @@ log.info(`Service proxy for geo data services is ${(config.enableServiceProxy ?
app.use('/', koop.server);

// create HTTP server
http.createServer(app)
const server = http.createServer(app)
.listen(config.port || 80);
log.info(`Koop MarkLogic Provider listening for HTTP on ${config.port}`);

Expand All @@ -66,3 +87,5 @@ if (config.ssl.enabled) {
}

console.log('Press control + c to exit');

module.exports = server; // make it testable
Loading

0 comments on commit 38c0674

Please sign in to comment.