Skip to content

feat(snowflake-driver): Introduce CUBEJS_DB_SNOWFLAKE_OAUTH_TOKEN env var / config option #9752

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ if [dedicated infrastructure][ref-dedicated-infra] is used. Check out the
| `CUBEJS_DB_SNOWFLAKE_PRIVATE_KEY` | The content of the private RSA key | Content of the private RSA key (encrypted or not) | ❌ |
| `CUBEJS_DB_SNOWFLAKE_PRIVATE_KEY_PATH` | The path to the private RSA key | A valid path to the private RSA key | ❌ |
| `CUBEJS_DB_SNOWFLAKE_PRIVATE_KEY_PASS` | The password for the private RSA key. Only required for encrypted keys | A valid password for the encrypted private RSA key | ❌ |
| `CUBEJS_DB_SNOWFLAKE_OAUTH_TOKEN` | The OAuth token | A valid OAuth token (string) | ❌ |
| `CUBEJS_DB_SNOWFLAKE_OAUTH_TOKEN_PATH` | The path to the valid oauth toket file | A valid path for the oauth token file | ❌ |
| `CUBEJS_DB_SNOWFLAKE_HOST` | Host address to which the driver should connect | A valid hostname | ❌ |
| `CUBEJS_DB_SNOWFLAKE_QUOTED_IDENTIFIERS_IGNORE_CASE` | Whether or not [quoted identifiers should be case insensitive][link-snowflake-quoted-identifiers]. Default is `false` | `true`, `false` | ❌ |
Expand Down
13 changes: 13 additions & 0 deletions packages/cubejs-backend-shared/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,19 @@ const variables: Record<string, (...args: any) => any> = {
]
),

/**
* Snowflake OAuth token (string).
*/
snowflakeOAuthToken: ({
dataSource
}: {
dataSource: string,
}) => (
process.env[
keyByDataSource('CUBEJS_DB_SNOWFLAKE_OAUTH_TOKEN', dataSource)
]
),

/**
* Snowflake OAuth token path.
*/
Expand Down
38 changes: 34 additions & 4 deletions packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ interface SnowflakeDriverOptions {
clientSessionKeepAlive?: boolean,
database?: string,
authenticator?: string,
oauthToken?: string,
oauthTokenPath?: string,
token?: string,
privateKeyPath?: string,
Expand Down Expand Up @@ -189,7 +190,7 @@ export class SnowflakeDriver extends BaseDriver implements DriverInterface {
/**
* Returns the configurable driver options
* Note: It returns the unprefixed option names.
* In case of using multisources options need to be prefixed manually.
* In case of using multi-sources options need to be prefixed manually.
*/
public static driverEnvVariables() {
return [
Expand All @@ -202,6 +203,7 @@ export class SnowflakeDriver extends BaseDriver implements DriverInterface {
'CUBEJS_DB_SNOWFLAKE_ROLE',
'CUBEJS_DB_SNOWFLAKE_CLIENT_SESSION_KEEP_ALIVE',
'CUBEJS_DB_SNOWFLAKE_AUTHENTICATOR',
'CUBEJS_DB_SNOWFLAKE_OAUTH_TOKEN',
'CUBEJS_DB_SNOWFLAKE_OAUTH_TOKEN_PATH',
'CUBEJS_DB_SNOWFLAKE_HOST',
'CUBEJS_DB_SNOWFLAKE_PRIVATE_KEY',
Expand Down Expand Up @@ -286,6 +288,7 @@ export class SnowflakeDriver extends BaseDriver implements DriverInterface {
username: getEnv('dbUser', { dataSource }),
password: getEnv('dbPass', { dataSource }),
authenticator: getEnv('snowflakeAuthenticator', { dataSource }),
oauthToken: getEnv('snowflakeOAuthToken', { dataSource }),
oauthTokenPath: getEnv('snowflakeOAuthTokenPath', { dataSource }),
privateKeyPath: getEnv('snowflakePrivateKeyPath', { dataSource }),
privateKeyPass: getEnv('snowflakePrivateKeyPass', { dataSource }),
Expand Down Expand Up @@ -423,12 +426,39 @@ export class SnowflakeDriver extends BaseDriver implements DriverInterface {
return token.trim();
}

private async createConnection() {
private async prepareConnectOptions(): Promise<snowflake.ConnectionOptions> {
const config: Record<string, any> = {
account: this.config.account,
region: this.config.region,
host: this.config.host,
application: this.config.application,
authenticator: this.config.authenticator,
clientSessionKeepAlive: this.config.clientSessionKeepAlive,
database: this.config.database,
warehouse: this.config.warehouse,
role: this.config.role,
resultPrefetch: this.config.resultPrefetch,
};

if (this.config.authenticator?.toUpperCase() === 'OAUTH') {
this.config.token = await this.readOAuthToken();
config.token = this.config.oauthToken || await this.readOAuthToken();
} else if (this.config.authenticator?.toUpperCase() === 'SNOWFLAKE_JWT') {
config.username = this.config.username;
config.privateKey = this.config.privateKey;
config.privateKeyPath = this.config.privateKeyPath;
config.privateKeyPass = this.config.privateKeyPass;
} else {
config.username = this.config.username;
config.password = this.config.password;
}

return snowflake.createConnection(this.config);
return config as snowflake.ConnectionOptions;
}

private async createConnection() {
const config = await this.prepareConnectOptions();

return snowflake.createConnection(config);
}

/**
Expand Down
Loading