Fix #3860: Add support for custom OIDC SSO (#3892)

This commit is contained in:
Daniel 2022-04-06 19:34:04 +03:00 committed by GitHub
parent a1e2b27f39
commit bb16bd5bde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 2 deletions

View File

@ -73,6 +73,26 @@
"additionalProperties": false, "additionalProperties": false,
"required": ["clientId", "secretKey", "domain"] "required": ["clientId", "secretKey", "domain"]
}, },
"customOidcSSOConfig": {
"description": "Custom OIDC SSO client security configs.",
"type": "object",
"properties": {
"clientId": {
"description": "Custom OIDC Client ID.",
"type": "string"
},
"secretKey": {
"description": "Custom OIDC Client Secret Key.",
"type": "string"
},
"tokenEndpoint": {
"description": "Custom OIDC token endpoint.",
"type": "string"
}
},
"additionalProperties": false,
"required": ["clientId", "secretKey", "tokenEndpoint"]
},
"openMetadataServerConfig": { "openMetadataServerConfig": {
"description": "OpenMetadata Server Connection Details.", "description": "OpenMetadata Server Connection Details.",
"type": "object", "type": "object",
@ -85,7 +105,7 @@
"authProvider": { "authProvider": {
"description": "OpenMetadata Server Authentication Provider. Make sure configure same auth providers as the one configured on OpenMetadaata server.", "description": "OpenMetadata Server Authentication Provider. Make sure configure same auth providers as the one configured on OpenMetadaata server.",
"type": "string", "type": "string",
"enum": ["no-auth", "google", "okta", "auth0"], "enum": ["no-auth", "google", "okta", "auth0", "custom-oidc"],
"default": "no-auth" "default": "no-auth"
}, },
"securityConfig": { "securityConfig": {
@ -99,6 +119,9 @@
}, },
{ {
"$ref": "#/definitions/auth0SSOConfig" "$ref": "#/definitions/auth0SSOConfig"
},
{
"$ref": "#/definitions/customOidcSSOConfig"
} }
] ]
}, },

View File

@ -63,6 +63,7 @@ from metadata.ingestion.ometa.mixins.version_mixin import OMetaVersionMixin
from metadata.ingestion.ometa.openmetadata_rest import ( from metadata.ingestion.ometa.openmetadata_rest import (
Auth0AuthenticationProvider, Auth0AuthenticationProvider,
AzureAuthenticationProvider, AzureAuthenticationProvider,
CustomOIDCAuthenticationProvider,
GoogleAuthenticationProvider, GoogleAuthenticationProvider,
NoOpAuthenticationProvider, NoOpAuthenticationProvider,
OktaAuthenticationProvider, OktaAuthenticationProvider,
@ -157,6 +158,10 @@ class OpenMetadata(
self._auth_provider: AuthenticationProvider = ( self._auth_provider: AuthenticationProvider = (
AzureAuthenticationProvider.create(self.config) AzureAuthenticationProvider.create(self.config)
) )
elif self.config.authProvider.value == "custom-oidc":
self._auth_provider: AuthenticationProvider = (
CustomOIDCAuthenticationProvider.create(self.config)
)
else: else:
self._auth_provider: AuthenticationProvider = ( self._auth_provider: AuthenticationProvider = (
NoOpAuthenticationProvider.create(self.config) NoOpAuthenticationProvider.create(self.config)

View File

@ -17,8 +17,9 @@ import json
import logging import logging
import sys import sys
import traceback import traceback
from typing import List from typing import List, Tuple
import requests
from pydantic import BaseModel from pydantic import BaseModel
from metadata.generated.schema.entity.data.dashboard import Dashboard from metadata.generated.schema.entity.data.dashboard import Dashboard
@ -30,6 +31,7 @@ from metadata.generated.schema.entity.services.databaseService import DatabaseSe
from metadata.generated.schema.entity.tags.tagCategory import Tag from metadata.generated.schema.entity.tags.tagCategory import Tag
from metadata.generated.schema.metadataIngestion.workflow import ( from metadata.generated.schema.metadataIngestion.workflow import (
Auth0SSOConfig, Auth0SSOConfig,
CustomOidcSSOConfig,
GoogleSSOConfig, GoogleSSOConfig,
OktaSSOConfig, OktaSSOConfig,
OpenMetadataServerConfig, OpenMetadataServerConfig,
@ -323,3 +325,51 @@ class AzureAuthenticationProvider(AuthenticationProvider):
def get_access_token(self): def get_access_token(self):
self.auth_token() self.auth_token()
return self.generated_auth_token, self.expiry return self.generated_auth_token, self.expiry
class CustomOIDCAuthenticationProvider(AuthenticationProvider):
"""
Custom OIDC authentication implementation
Args:
config (MetadataServerConfig):
Attributes:
config (MetadataServerConfig)
"""
def __init__(self, config: OpenMetadataServerConfig) -> None:
self.config = config
self.security_config: CustomOidcSSOConfig = self.config.securityConfig
self.generated_auth_token = None
self.expiry = None
@classmethod
def create(
cls, config: OpenMetadataServerConfig
) -> "CustomOIDCAuthenticationProvider":
return cls(config)
def auth_token(self) -> None:
data = {
"grant_type": "client_credentials",
"client_id": self.security_config.clientId,
"client_secret": self.security_config.secretKey,
}
response = requests.post(
url=self.security_config.tokenEndpoint,
data=data,
)
if response.ok:
response_json = response.json()
self.generated_auth_token = response_json["access_token"]
self.expiry = response_json["expires_in"]
else:
raise APIError(
error={"message": response.text}, http_error=response.status_code
)
def get_access_token(self) -> Tuple[str, int]:
self.auth_token()
return self.generated_auth_token, self.expiry