Skip to content

Commit

Permalink
Add Basic Auth
Browse files Browse the repository at this point in the history
  • Loading branch information
jwulf committed Nov 16, 2019
1 parent 8cef414 commit bd261a7
Show file tree
Hide file tree
Showing 14 changed files with 134 additions and 46 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
dist
docs
.DS_Store
.DS_Store
.vscode
20 changes: 0 additions & 20 deletions .vscode/settings.json

This file was deleted.

8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# Version 0.22.0

- Breaking Change: the signature for specifying a workflow definition version in `createWorkflowInstance` has changed. See the README for the new signature.
- Breaking Change: The signature for specifying a workflow definition version in `createWorkflowInstance` has changed. See the README for the new signature.
- Breaking Change: Change `pollMode` to `pollInterval` in logging.
- Breaking Change: Change default long poll to 30s. See [#101](https://github.com/creditsenseau/zeebe-client-node-js/issues/101).
- Feature: Add support for Basic Auth
- Feature: Awaitable workflow outcome. The client can initiate a workflow and receive the outcome of the workflow in the response. See [zeebe/#2896](https://github.com/zeebe-io/zeebe/issues/2896).
- Change default long poll to 30s. See [#101](https://github.com/creditsenseau/zeebe-client-node-js/issues/101).
- Fix: Correctly log task type from gRPC client.
- Change `pollMode` to `pollInterval` in logging.
- Chore: Upgrade TypeScript to 3.7

# Version 0.21.3

Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,22 @@ const zbc = new ZB.ZBClient("my-secure-broker.io:443", {
The `cacheOnDisk` option will cache the token on disk, which can be useful in development if you are restarting the service frequently.
## Basic Auth
If you put a proxy in front of the broker with basic auth, you can pass in a username and password:
```typescript
const zbc = new ZB.ZBClient("my-broker-with-basic-auth.io:443", {
basicAuth: {
username: "user1",
password: "secret",
},
useTLS: true
}
```
Basic Auth will also work without TLS.
### Camunda Cloud
You can connect to Camunda Cloud by using the `camundaCloud` configuration option, using the `clusterId`, `clientSecret`, and `clientId` from the Camunda Cloud Console, like this:
Expand Down Expand Up @@ -223,6 +239,13 @@ ZEEBE_AUTHORIZATION_SERVER_URL
ZEEBE_GATEWAY_ADDRESS
```
Basic Auth:
```
ZEEBE_BASIC_AUTH_PASSWORD
ZEEBE_BASIC_AUTH_USERNAME
```
### Create a Task Worker
```javascript
Expand Down
20 changes: 20 additions & 0 deletions docker/basic-auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ZBClient } from '../src'

// Add an entry to your /etc/hosts to resolve zeebe.docker.localhost to 127.0.0.1

const z = new ZBClient('zeebe.docker.localhost:80', {
basicAuth: {
password: 'test',
username: 'test',
},
})

async function main() {
// tslint:disable-next-line: no-console
console.log(await z.topology())
z.createWorker(null, 't', (_, complete) => {
complete.success()
})
}

main()
34 changes: 25 additions & 9 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
version: "2"
# Basic Auth setup

version: "3"

services:
nginx-proxy:
image: jwilder/nginx-proxy:alpine
container_name: nginx-proxy
reverse-proxy:
# The official v2.0 Traefik docker image
image: traefik:v2.0
# Enables the web UI and tells Traefik to listen to docker
command: --api.insecure=true --providers.docker
ports:
- "80:26500"
# The HTTP port
- "80:80"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock

zeebe:
image: camunda/zeebe:0.22.0-alpha1
environment:
- VIRTUAL_HOST=whoami.local
- VIRTUAL_PORT=26500
labels:
# Resolvable name, for routing the incoming connections
- "traefik.http.routers.zeebe.rule=Host(`zeebe.docker.localhost`)"
## Unencrypted HTTP2 traffic between proxy and Zeebe
- "traefik.http.services.zeebe.loadbalancer.server.scheme=h2c"
# Note: all dollar signs in the hash need to be doubled for escaping.
# To create user:password pair, it's possible to use this command:
# echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
- "traefik.http.middlewares.zeebe-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
- "traefik.http.routers.zeebe.middlewares=zeebe-auth"
18 changes: 13 additions & 5 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"tslint-config-prettier": "^1.18.0",
"typedoc": "^0.15.0",
"typedoc-plugin-sourcefile-url": "^1.0.4",
"typescript": "^3.2.2"
"typescript": "^3.7.2"
},
"author": {
"name": "Josh Wulf",
Expand Down
4 changes: 4 additions & 0 deletions src/lib/BasicAuthConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface BasicAuthConfig {
password: string
username: string
}
15 changes: 15 additions & 0 deletions src/lib/ConfigurationHydrator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { parse } from 'url'
import { BasicAuthConfig } from './BasicAuthConfig'
import * as ZB from './interfaces'
import { OAuthProviderConfig } from './OAuthProvider'

Expand All @@ -11,6 +12,7 @@ export class ConfigurationHydrator {
const configuration = {
hostname: 'localhost',
port: '26500',
...ConfigurationHydrator.readBasicAuthFromEnvironment(),
...ConfigurationHydrator.readOAuthFromEnvironment(),
...ConfigurationHydrator.getGatewayFromEnvironment(),
...ConfigurationHydrator.readCamundaClusterConfFromEnv(
Expand Down Expand Up @@ -57,6 +59,19 @@ export class ConfigurationHydrator {
: {}
}

private static readBasicAuthFromEnvironment(): BasicAuthConfig | {} {
const password = process.env.ZEEBE_BASIC_AUTH_PASSWORD
const username = process.env.ZEEBE_BASIC_AUTH_USERNAME
return password && username
? {
basicAuth: {
password,
username,
},
}
: {}
}

private static readCamundaClusterConfFromEnv(explicitGateway?: string) {
if (explicitGateway) {
return {}
Expand Down
18 changes: 15 additions & 3 deletions src/lib/GRPCClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { loadSync, Options, PackageDefinition } from '@grpc/proto-loader'
import chalk from 'chalk'
import { EventEmitter } from 'events'
import { Client, credentials, loadPackageDefinition, Metadata } from 'grpc'
import { BasicAuthConfig } from './BasicAuthConfig'
import { Loglevel } from './interfaces'
import { OAuthProvider } from './OAuthProvider'
import { ZBLogger } from './ZBLogger'
Expand Down Expand Up @@ -79,8 +80,10 @@ export class GRPCClient extends EventEmitter {
private failTimer?: NodeJS.Timeout
private connectionTolerance: number
private onConnectionError?: () => void
private basicAuth?: BasicAuthConfig

constructor({
basicAuth,
connectionTolerance,
host,
loglevel,
Expand All @@ -95,6 +98,7 @@ export class GRPCClient extends EventEmitter {
onConnectionError,
onReady,
}: {
basicAuth?: BasicAuthConfig
connectionTolerance: number
host: string
loglevel: Loglevel
Expand All @@ -111,6 +115,7 @@ export class GRPCClient extends EventEmitter {
}) {
super()
this.oAuth = oAuth
this.basicAuth = basicAuth
this.longPoll = options.longPoll
this.connectionTolerance = connectionTolerance

Expand Down Expand Up @@ -222,7 +227,7 @@ export class GRPCClient extends EventEmitter {
// return this.client[methodName](data, { deadline })
// } else {
try {
const metadata = await this.getJWT()
const metadata = await this.getAuthToken()
stream = this.client[methodName](data, metadata)
} catch (e) {
this.logger.error(e)
Expand All @@ -245,7 +250,7 @@ export class GRPCClient extends EventEmitter {
const client = this.client
return new Promise(async (resolve, reject) => {
try {
const metadata = await this.getJWT()
const metadata = await this.getAuthToken()
client[methodName](data, metadata, (err, dat) => {
// This will error on network or business errors
if (err) {
Expand Down Expand Up @@ -333,13 +338,20 @@ export class GRPCClient extends EventEmitter {
})
}

private async getJWT() {
private async getAuthToken() {
let metadata
if (this.oAuth) {
const token = await this.oAuth.getToken()
metadata = new Metadata()
metadata.add('Authorization', `Bearer ${token}`)
}
if (this.basicAuth) {
const token = Buffer.from(
`${this.basicAuth.username}:${this.basicAuth.password}`
).toString('base64')
metadata = new Metadata()
metadata.add('Authorization', `Basic ${token}`)
}
return metadata
}

Expand Down
4 changes: 4 additions & 0 deletions src/lib/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ export interface ZBClientOptions {
maxRetries?: number
maxRetryTimeout?: number
oAuth?: OAuthProviderConfig
basicAuth?: {
username: string
password: string
}
useTLS?: boolean
longPoll?: number
camundaCloud?: CamundaCloudConfig
Expand Down
5 changes: 4 additions & 1 deletion src/zb/ZBClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as path from 'path'
import promiseRetry from 'promise-retry'
import { v4 as uuid } from 'uuid'
import { BpmnParser, parseVariables, stringifyVariables } from '../lib'
import { BasicAuthConfig } from '../lib/BasicAuthConfig'
import { ConfigurationHydrator } from '../lib/ConfigurationHydrator'
import { GRPCClient } from '../lib/GRPCClient'
import * as ZB from '../lib/interfaces'
Expand Down Expand Up @@ -43,6 +44,7 @@ export class ZBClient {
private maxRetries: number
private maxRetryTimeout: number
private oAuth?: OAuthProvider
private basicAuth?: BasicAuthConfig
private useTLS: boolean
private stdout: any
private lastReady?: Date
Expand Down Expand Up @@ -97,7 +99,7 @@ export class ZBClient {
this.useTLS =
this.options.useTLS === true ||
(!!this.options.oAuth && this.options.useTLS !== false)

this.basicAuth = this.options.basicAuth
this.connectionTolerance =
this.options.connectionTolerance || this.connectionTolerance
this.onConnectionError = this.options.onConnectionError
Expand Down Expand Up @@ -540,6 +542,7 @@ export class ZBClient {
tasktype: string
}) {
return new GRPCClient({
basicAuth: this.basicAuth,
connectionTolerance: this.connectionTolerance,
host: this.gatewayAddress,
loglevel: this.loglevel,
Expand Down
6 changes: 3 additions & 3 deletions src/zb/ZBWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export class ZBWorker<

public completeJob(
completeJobRequest: ZB.CompleteJobRequest
): Promise<void> {
): Promise<any> {
const withStringifiedVariables = stringifyVariables(completeJobRequest)
this.logger.debug(withStringifiedVariables)
return this.gRPCClient.completeJobSync(withStringifiedVariables)
Expand Down Expand Up @@ -335,15 +335,15 @@ export class ZBWorker<
}
},
success: async (completedVariables = {}) => {
await this.completeJob({
const res = await this.completeJob({
jobKey: job.key,
variables: completedVariables,
})
this.drainOne()
this.logger.debug(
`Completed task ${taskId} for ${this.taskType}`
)
return true
return res
},
}

Expand Down

0 comments on commit bd261a7

Please sign in to comment.