-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #181 from Canner/feature/authenticator
Feature: Canner PAT authenticator
- Loading branch information
Showing
28 changed files
with
582 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"extends": ["../../.eslintrc.json"], | ||
"ignorePatterns": ["!**/*"], | ||
"overrides": [ | ||
{ | ||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.ts", "*.tsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.js", "*.jsx"], | ||
"rules": {} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# extension-authenticator-canner | ||
|
||
This extension make Data API(VulcanSQL API) can integrate with [Canner Enterprise](https://cannerdata.com/product) and use Canner as a authenticate server | ||
|
||
This extension let Data API request can be authenticated with [Canner PAT](https://docs.cannerdata.com/product/api_sdk/api_personal_access_token) | ||
|
||
## Install | ||
|
||
1. Install package | ||
|
||
```sql | ||
npm i @vulcan-sql/extension-authenticator-canner | ||
``` | ||
|
||
2. Update `vulcan.yaml`, enable the extension and enable the `auth` configuration. | ||
|
||
```yaml | ||
auth: | ||
enabled: true | ||
# The extension-authenticator-canner and [build-in authenticator](https://vulcansql.com/docs/data-privacy/authn) can work at the same time | ||
extensions: | ||
canner-authenticator: '@vulcan-sql/extension-authenticator-canner' | ||
``` | ||
|
||
3. Update `vulcan.yaml`, define your `canner-authenticator` | ||
```yaml | ||
canner-authenticator: | ||
# To having the same config structure to the authenticator middleware, we | ||
options: | ||
canner-pat: | ||
# your canner enterprise host | ||
host: 'my-canner-host-dns' | ||
# your canner enterprise post | ||
post: 443 | ||
# indicate using http or https default is false | ||
ssl: true | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module.exports = { | ||
displayName: 'extension-authenticator-canner', | ||
preset: '../../jest.preset.ts', | ||
globals: { | ||
'ts-jest': { | ||
tsconfig: '<rootDir>/tsconfig.spec.json', | ||
}, | ||
}, | ||
transform: { | ||
'^.+\\.[tj]s$': 'ts-jest', | ||
}, | ||
moduleFileExtensions: ['ts', 'js', 'html'], | ||
coverageDirectory: '../../coverage/packages/extension-authenticator-canner', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"name": "@vulcan-sql/extension-authenticator-canner", | ||
"description": "Canner Enterprise authenticator for Vulcan SQL", | ||
"version": "0.4.0", | ||
"type": "commonjs", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"keywords": [ | ||
"vulcan", | ||
"vulcan-sql", | ||
"data", | ||
"sql", | ||
"database", | ||
"data-warehouse", | ||
"data-lake", | ||
"api-builder", | ||
"postgres", | ||
"pg" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/Canner/vulcan.git" | ||
}, | ||
"license": "MIT", | ||
"peerDependencies": { | ||
"@vulcan-sql/core": "~0.4.0-0", | ||
"@vulcan-sql/serve": "~0.4.0-0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"root": "packages/extension-authenticator-canner", | ||
"sourceRoot": "packages/extension-authenticator-canner/src", | ||
"targets": { | ||
"build": { | ||
"executor": "@nrwl/js:tsc", | ||
"outputs": ["{options.outputPath}"], | ||
"options": { | ||
"outputPath": "dist/packages/extension-authenticator-canner", | ||
"main": "packages/extension-authenticator-canner/src/index.ts", | ||
"tsConfig": "packages/extension-authenticator-canner/tsconfig.lib.json", | ||
"assets": ["packages/extension-authenticator-canner/*.md"] | ||
} | ||
}, | ||
"lint": { | ||
"executor": "@nrwl/linter:eslint", | ||
"outputs": ["{options.outputFile}"], | ||
"options": { | ||
"lintFilePatterns": ["packages/extension-authenticator-canner/**/*.ts"] | ||
} | ||
}, | ||
"test": { | ||
"executor": "@nrwl/jest:jest", | ||
"outputs": ["coverage/packages/extension-authenticator-canner"], | ||
"options": { | ||
"jestConfig": "packages/extension-authenticator-canner/jest.config.ts", | ||
"passWithNoTests": true | ||
} | ||
} | ||
}, | ||
"tags": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { CannerPATAuthenticator } from './lib'; | ||
|
||
export default [CannerPATAuthenticator]; |
1 change: 1 addition & 0 deletions
1
packages/extension-authenticator-canner/src/lib/authenticator/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './pat'; |
120 changes: 120 additions & 0 deletions
120
packages/extension-authenticator-canner/src/lib/authenticator/pat.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import { | ||
ConfigurationError, | ||
VulcanExtensionId, | ||
InternalError, | ||
} from '@vulcan-sql/core'; | ||
import { | ||
BaseAuthenticator, | ||
KoaContext, | ||
AuthStatus, | ||
AuthResult, | ||
} from '@vulcan-sql/serve'; | ||
import { isEmpty } from 'lodash'; | ||
import axios from 'axios'; | ||
import config from '../config'; | ||
|
||
export interface CannerPATOptions { | ||
host: string; | ||
port: number; | ||
// default is false | ||
ssl: boolean; | ||
} | ||
|
||
@VulcanExtensionId('canner-pat') | ||
export class CannerPATAuthenticator extends BaseAuthenticator<CannerPATOptions> { | ||
private options: CannerPATOptions = {} as CannerPATOptions; | ||
|
||
public override async onActivate() { | ||
this.options = this.getOptions() as CannerPATOptions; | ||
} | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
public async getTokenInfo(ctx: KoaContext): Promise<any> { | ||
throw new InternalError(`canner-pat does not support token generate.`); | ||
} | ||
|
||
public async authCredential(context: KoaContext) { | ||
const incorrect = { | ||
status: AuthStatus.INDETERMINATE, | ||
type: this.getExtensionId()!, | ||
}; | ||
const authorize = context.request.headers['authorization']; | ||
if ( | ||
// no need to check this.options because it a external extension, | ||
// it must be configured correctly to be load into container and can be used in authenticate middleware | ||
!authorize || | ||
!authorize.toLowerCase().startsWith(this.getExtensionId()!) | ||
) | ||
return incorrect; | ||
|
||
if (isEmpty(this.options) || !this.options.host) | ||
throw new ConfigurationError( | ||
'please provide correct connection information to Canner Enterprise, including "host".' | ||
); | ||
|
||
// validate request auth token | ||
const token = authorize.trim().split(' ')[1]; | ||
|
||
try { | ||
return await this.validate(token); | ||
} catch (err) { | ||
return { | ||
status: AuthStatus.FAIL, | ||
type: this.getExtensionId()!, | ||
message: (err as Error).message, | ||
}; | ||
} | ||
} | ||
|
||
private async validate(token: string) { | ||
const res = await this.fetchCannerUser(token); | ||
const cannerUser = res.data.data?.userMe; | ||
const { username, ...restAttrs } = cannerUser; | ||
return { | ||
status: AuthStatus.SUCCESS, | ||
type: this.getExtensionId()!, // method name | ||
user: { | ||
name: username, | ||
attr: restAttrs, | ||
}, | ||
} as AuthResult; | ||
} | ||
|
||
private async fetchCannerUser(token: string) { | ||
const graphqlUrl = this.getCannerUrl('/web/graphql'); | ||
try { | ||
return await axios.post( | ||
graphqlUrl, | ||
{ | ||
operationName: 'UserMe', | ||
variables: {}, | ||
query: | ||
'query UserMe{userMe {accountRole attributes createdAt email groups {id name} lastName firstName username}}', | ||
}, | ||
{ | ||
headers: { | ||
Authorization: `Token ${token}`, | ||
}, | ||
} | ||
); | ||
} catch (error: any) { | ||
const message = error.response | ||
? `response status: ${ | ||
error.response.status | ||
}, response data: ${JSON.stringify(error.response.data)}` | ||
: `remote server does not response. request ${error.toJSON()}}`; | ||
throw new InternalError( | ||
`Failed to fetch user info from canner server: ${message}` | ||
); | ||
} | ||
} | ||
private getCannerUrl(path = '/') { | ||
const { host, port, ssl = false } = this.options; | ||
if (config.isOnKubernetes) | ||
return `http://${process.env['WEB_SERVICE_HOST']}${path}`; // for internal usage, we don't need to specify port | ||
else { | ||
const protocol = ssl ? 'https' : 'http'; | ||
return `${protocol}://${host}${port ? `:${port}` : ''}${path}`; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export interface IEnvConfig { | ||
// indicates whether the extension is running in k8s | ||
isOnKubernetes?: boolean; | ||
} | ||
|
||
const config: IEnvConfig = { | ||
isOnKubernetes: Boolean(process.env['IS_ON_KUBERNETES']) || false, | ||
}; | ||
|
||
export default config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './authenticator/pat'; |
Oops, something went wrong.