Skip to content

Commit

Permalink
feat: token auth
Browse files Browse the repository at this point in the history
  • Loading branch information
grutt committed Jan 27, 2024
1 parent 3488e63 commit 67c20f2
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 34 deletions.
9 changes: 3 additions & 6 deletions frontend/docs/pages/typescript-sdk/setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,10 @@ yarn add @hatchet/node-sdk

## Usage

You should have generated a set of client certificates (or received them through Hatchet cloud). These certificates are `ca.cert`, `client-worker.pem`, and `client-worker.key`. You should also make note of the Hatchet server address and the tenant ID you'd like to connect to.
Navigate to `https://app.dev.hatchet-tools.com/tenant-settings` to generate an API Token and set the following environment variables.

```sh
HATCHET_CLIENT_TENANT_ID=<tenant-id>
HATCHET_CLIENT_TLS_ROOT_CA_FILE=./certs/ca.cert
HATCHET_CLIENT_TLS_CERT_FILE=./certs/client-worker.pem
HATCHET_CLIENT_TLS_KEY_FILE=./certs/client-worker.key
HATCHET_CLIENT_TLS_SERVER_NAME=<hatchet-domain>
HATCHET_CLIENT_HOST_PORT=<hatchet-domain>:443
HATCHET_CLIENT_TOKEN=<your-token>
HATCHET_CLIENT_HOST_PORT=<hatchet-domain>:<hatchet-port>
```
8 changes: 5 additions & 3 deletions typescript-sdk/hatchet/clients/admin/admin-client.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CreateWorkflowVersionOpts, WorkflowVersion } from '@protoc/workflows';
import { AdminClient } from './admin-client';
import { mockChannel } from '../hatchet-client/hatchet-client.test';
import { mockChannel, mockFactory } from '../hatchet-client/hatchet-client.test';

describe('AdminClient', () => {
let client: AdminClient;
Expand All @@ -18,7 +18,8 @@ describe('AdminClient', () => {
server_name: 'TLS_SERVER_NAME',
},
},
mockChannel
mockChannel,
mockFactory
);

expect(x).toBeDefined();
Expand All @@ -37,7 +38,8 @@ describe('AdminClient', () => {
server_name: 'TLS_SERVER_NAME',
},
},
mockChannel
mockChannel,
mockFactory
);
});

Expand Down
6 changes: 3 additions & 3 deletions typescript-sdk/hatchet/clients/admin/admin-client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Channel, createClient } from 'nice-grpc';
import { Channel, ClientFactory } from 'nice-grpc';
import {
CreateWorkflowVersionOpts,
WorkflowServiceClient,
Expand All @@ -11,9 +11,9 @@ export class AdminClient {
config: ClientConfig;
client: WorkflowServiceClient;

constructor(config: ClientConfig, channel: Channel) {
constructor(config: ClientConfig, channel: Channel, factory: ClientFactory) {
this.config = config;
this.client = createClient(WorkflowServiceDefinition, channel);
this.client = factory.create(WorkflowServiceDefinition, channel);
}

async put_workflow(workflow: CreateWorkflowVersionOpts, options?: { autoVersion?: boolean }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import sleep from '@util/sleep';
import { ServerError, Status } from 'nice-grpc-common';
import { DispatcherClient } from './dispatcher-client';
import { ActionListener } from './action-listener';
import { mockChannel } from '../hatchet-client/hatchet-client.test';
import { mockChannel, mockFactory } from '../hatchet-client/hatchet-client.test';

let dispatcher: DispatcherClient;

Expand Down Expand Up @@ -55,7 +55,8 @@ describe('ActionListener', () => {
server_name: 'TLS_SERVER_NAME',
},
},
mockChannel
mockChannel,
mockFactory
);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ActionEventType } from '@protoc/dispatcher';
import { DispatcherClient } from './dispatcher-client';
import { mockChannel } from '../hatchet-client/hatchet-client.test';
import { mockChannel, mockFactory } from '../hatchet-client/hatchet-client.test';

let client: DispatcherClient;

Expand All @@ -19,7 +19,8 @@ describe('DispatcherClient', () => {
server_name: 'TLS_SERVER_NAME',
},
},
mockChannel
mockChannel,
mockFactory
);

expect(x).toBeDefined();
Expand All @@ -39,7 +40,8 @@ describe('DispatcherClient', () => {
server_name: 'TLS_SERVER_NAME',
},
},
mockChannel
mockChannel,
mockFactory
);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Channel, createClient } from 'nice-grpc';
import { Channel, ClientFactory } from 'nice-grpc';
import {
DispatcherClient as PbDispatcherClient,
DispatcherDefinition,
Expand All @@ -18,9 +18,9 @@ export class DispatcherClient {
config: ClientConfig;
client: PbDispatcherClient;

constructor(config: ClientConfig, channel: Channel) {
constructor(config: ClientConfig, channel: Channel, factory: ClientFactory) {
this.config = config;
this.client = createClient(DispatcherDefinition, channel);
this.client = factory.create(DispatcherDefinition, channel);
}

async get_action_listener(options: GetActionListenerOptions) {
Expand Down
10 changes: 5 additions & 5 deletions typescript-sdk/hatchet/clients/event/event-client.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import HatchetError from '@util/errors/hatchet-error';
import { createChannel } from 'nice-grpc';
import { EventClient } from './event-client';
import { mockChannel, mockFactory } from '../hatchet-client/hatchet-client.test';

let client: EventClient;

const mockChannel = createChannel('localhost:50051');

describe('EventClient', () => {
it('should create a client', () => {
const x = new EventClient(
Expand All @@ -20,7 +18,8 @@ describe('EventClient', () => {
server_name: 'TLS_SERVER_NAME',
},
},
mockChannel
mockChannel,
mockFactory
);

expect(x).toBeDefined();
Expand All @@ -39,7 +38,8 @@ describe('EventClient', () => {
server_name: 'TLS_SERVER_NAME',
},
},
mockChannel
mockChannel,
mockFactory
);
});

Expand Down
7 changes: 3 additions & 4 deletions typescript-sdk/hatchet/clients/event/event-client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Channel, createClient } from 'nice-grpc';
import { Channel, ClientFactory } from 'nice-grpc';
import {
EventsServiceClient,
EventsServiceDefinition,
Expand All @@ -11,10 +11,9 @@ export class EventClient {
config: ClientConfig;
client: EventsServiceClient;

constructor(config: ClientConfig, channel: Channel) {
constructor(config: ClientConfig, channel: Channel, factory: ClientFactory) {
this.config = config;

this.client = createClient(EventsServiceDefinition, channel);
this.client = factory.create(EventsServiceDefinition, channel);
}

push<T>(type: string, input: T) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ChannelCredentials, createChannel } from 'nice-grpc';
import { ChannelCredentials, createChannel, createClientFactory } from 'nice-grpc';
import { HatchetClient } from './hatchet-client';

export const mockChannel = createChannel('localhost:50051');
export const mockFactory = createClientFactory();

describe('Client', () => {
beforeEach(() => {
Expand Down
42 changes: 38 additions & 4 deletions typescript-sdk/hatchet/clients/hatchet-client/hatchet-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ import { ConfigLoader } from '@util/config-loader';
import { EventClient } from '@clients/event/event-client';
import { DispatcherClient } from '@clients/dispatcher/dispatcher-client';
import { AdminClient } from '@clients/admin/admin-client';
import { Channel, ChannelCredentials, createChannel } from 'nice-grpc';
import {
CallOptions,
Channel,
ChannelCredentials,
ClientMiddlewareCall,
Metadata,
createChannel,
createClientFactory,
} from 'nice-grpc';
import { Workflow } from '@hatchet/workflow';
import { Worker } from '@clients/worker';
import Logger from '@hatchet/util/logger/logger';
Expand All @@ -14,6 +22,29 @@ export interface HatchetClientOptions {
credentials?: ChannelCredentials;
}

const addTokenMiddleware = (token: string) =>
async function* _<Request, Response>(
call: ClientMiddlewareCall<Request, Response>,
options: CallOptions
) {
const optionsWithAuth: CallOptions = {
...options,
metadata: new Metadata({ authorization: `'Bearer ${token}` }),
};

if (!call.responseStream) {
const response = yield* call.next(call.request, optionsWithAuth);

return response;
}

for await (const response of call.next(call.request, optionsWithAuth)) {
yield response;
}

return undefined;
};

export class HatchetClient {
config: ClientConfig;
credentials: ChannelCredentials;
Expand Down Expand Up @@ -48,13 +79,16 @@ export class HatchetClient {

this.credentials =
options?.credentials ?? ConfigLoader.createCredentials(this.config.tls_config);

this.channel = createChannel(this.config.host_port, this.credentials, {
'grpc.ssl_target_name_override': this.config.tls_config.server_name,
});

this.event = new EventClient(this.config, this.channel);
this.dispatcher = new DispatcherClient(this.config, this.channel);
this.admin = new AdminClient(this.config, this.channel);
const clientFactory = createClientFactory().use(addTokenMiddleware(this.config.token));

this.event = new EventClient(this.config, this.channel, clientFactory);
this.dispatcher = new DispatcherClient(this.config, this.channel, clientFactory);
this.admin = new AdminClient(this.config, this.channel, clientFactory);

this.logger = new Logger('HatchetClient', this.config.log_level);

Expand Down

0 comments on commit 67c20f2

Please sign in to comment.