Skip to content

Commit

Permalink
feat: custom root certificate support (#19)
Browse files Browse the repository at this point in the history
Release-As: 0.0.3
  • Loading branch information
DaniAkash authored Jul 2, 2024
1 parent 3d46b72 commit 8b517f4
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 1 deletion.
33 changes: 32 additions & 1 deletion src/client/auth/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import resources_pb2 from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"
import { grpc } from "clarifai-nodejs-grpc";
import { V2Client } from "clarifai-nodejs-grpc/proto/clarifai/api/service_grpc_pb";
import process from "process";
import fs from "fs";

// TypeScript interface for the cache
export interface Cache {
Expand Down Expand Up @@ -75,6 +76,7 @@ export class ClarifaiAuthHelper {
private token: string;
private _base: string;
private _ui: string;
private _rootCertificatesPath: string;

/**
* A helper to get the authorization information needed to make API calls with the grpc
Expand All @@ -97,6 +99,7 @@ export class ClarifaiAuthHelper {
* https://clarifai.com (default), https://host:port, http://host:port,
* host:port (will be treated as http, not https). It's highly recommended to include
* the http:// or https:// otherwise we need to check the endpoint to determine if it has SSL during this __init__.
* @param rootCertificatesPath - path to the root certificates file. This is only used for grpc secure channels.
* @param validate - Whether to validate the inputs. This is useful for overriding vars then validating.
*/
constructor(
Expand All @@ -106,12 +109,14 @@ export class ClarifaiAuthHelper {
token: string = "",
base: string = DEFAULT_BASE,
ui: string = DEFAULT_UI,
rootCertificatesPath: string = "",
validate: boolean = true,
) {
this.userId = userId;
this.appId = appId;
this._pat = pat;
this.token = token;
this._rootCertificatesPath = rootCertificatesPath;
this._base = base;
this._ui = ui;

Expand Down Expand Up @@ -142,6 +147,13 @@ export class ClarifaiAuthHelper {
throw new Error(
"Need 'pat' or 'token' in the query params or use one of the CLARIFAI_PAT or CLARIFAI_SESSION_TOKEN env vars",
);
} else if (
this._rootCertificatesPath &&
!fs.existsSync(this._rootCertificatesPath)
) {
throw new Error(
`Root certificates path ${this._rootCertificatesPath} does not exist`,
);
}
}

Expand All @@ -163,6 +175,8 @@ export class ClarifaiAuthHelper {
const pat = process.env.CLARIFAI_PAT || "";
const base = process.env.CLARIFAI_API_BASE || DEFAULT_BASE;
const ui = process.env.CLARIFAI_UI || DEFAULT_UI;
const rootCertificatesPath =
process.env.CLARIFAI_ROOT_CERTIFICATES_PATH || "";

return new ClarifaiAuthHelper(
userId,
Expand All @@ -171,6 +185,7 @@ export class ClarifaiAuthHelper {
token,
base,
ui,
rootCertificatesPath,
validate,
);
}
Expand Down Expand Up @@ -227,7 +242,16 @@ export class ClarifaiAuthHelper {
let client: V2Client;

if (https) {
client = new V2Client(this._base, grpc.ChannelCredentials.createSsl());
if (this._rootCertificatesPath) {
client = new V2Client(
this._base,
grpc.ChannelCredentials.createSsl(
fs.readFileSync(this._rootCertificatesPath),
),
);
} else {
client = new V2Client(this._base, grpc.ChannelCredentials.createSsl());
}
} else {
let host: string;
let port: number = 80;
Expand Down Expand Up @@ -282,6 +306,13 @@ export class ClarifaiAuthHelper {
this._ui = httpsCache(uiHttpsCache, ui);
}

/**
* Return the root certificates path.
*/
get rootCertificatesPath(): string {
return this._rootCertificatesPath;
}

/**
* Return the base domain for the API.
*/
Expand Down
4 changes: 4 additions & 0 deletions src/client/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export class BaseClient {
protected pat: string;
protected userAppId: UserAppIDSet;
protected base: string;
protected rootCertificatesPath: string;

/**
* Constructs a new BaseClient instance with specified configuration options.
Expand All @@ -39,6 +40,7 @@ export class BaseClient {
* @param {string} [authConfig.token] An optional token for authentication.
* @param {string} [authConfig.base='https://api.clarifai.com'] The base URL for the API endpoint. Defaults to 'https://api.clarifai.com'.
* @param {string} [authConfig.ui='https://clarifai.com'] The URL for the UI. Defaults to 'https://clarifai.com'.
* @param {string} [authConfig.rootCertificatesPath] Path to the SSL root certificates file, used to establish secure gRPC connections.
*/
constructor(authConfig: AuthConfig = {}) {
const pat = getFromDictOrEnv("pat", "CLARIFAI_PAT", authConfig);
Expand All @@ -52,6 +54,7 @@ export class BaseClient {
authConfig.token,
authConfig.base,
authConfig.ui,
authConfig.rootCertificatesPath,
false,
)
: ClarifaiAuthHelper.fromEnv(false); // The validate parameter is set to false explicitly
Expand All @@ -60,6 +63,7 @@ export class BaseClient {
this.pat = this.authHelper.pat;
this.userAppId = this.authHelper.getUserAppIdProto();
this.base = this.authHelper.base;
this.rootCertificatesPath = this.authHelper.rootCertificatesPath;
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export type AuthConfig =
userId: string;
appId: string;
pat: string;
rootCertificatesPath?: string;
token?: string;
base?: string;
ui?: string;
Expand Down
15 changes: 15 additions & 0 deletions tests/client/auth/helper.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,21 @@ describe("ClarifaiAuthHelper", () => {
expect(() => ClarifaiAuthHelper.validateSecretsDict(secrets)).toThrow();
});

it("throws error for invalid root certificates path", () => {
expect(
() =>
new ClarifaiAuthHelper(
"userId",
"appId",
"pat",
"",
"https://customdomain.com",
"https://customdomain.com/ui",
"invalid",
),
).toThrow(`Root certificates path invalid does not exist`);
});

it("getUserAppIdProto returns correct UserAppIDSet proto object", () => {
const helper = new ClarifaiAuthHelper("userId", "appId", "pat");
const userAppIdProto = helper.getUserAppIdProto();
Expand Down

0 comments on commit 8b517f4

Please sign in to comment.