diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/JwtFilter.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/JwtFilter.java
index 61dfde20e21..9f1918023f3 100644
--- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/JwtFilter.java
+++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/security/JwtFilter.java
@@ -95,7 +95,7 @@ public class JwtFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) {
UriInfo uriInfo = requestContext.getUriInfo();
- if (uriInfo.getPath().contains("config")) {
+ if (uriInfo.getPath().contains("config") || uriInfo.getPath().contains("version")) {
return;
}
diff --git a/openmetadata-clients/openmetadata-java-client/pom.xml b/openmetadata-clients/openmetadata-java-client/pom.xml
new file mode 100644
index 00000000000..f43b3ae0ea4
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/pom.xml
@@ -0,0 +1,138 @@
+
+
+
+
+ openmetadata-clients
+ org.openmetadata
+ 0.11.0-SNAPSHOT
+
+ 4.0.0
+
+ openmetadata-java-client
+
+ 11
+ ${java.version}
+ ${java.version}
+ 2.7.0
+ 9.7.0
+
+
+
+ org.openmetadata
+ openmetadata-core
+ ${project.version}
+
+
+ io.swagger
+ swagger-codegen-maven-plugin
+ 3.0.0-rc1
+
+
+ com.github.joschi.jackson
+ jackson-datatype-threetenbp
+ 2.6.4
+
+
+ org.apache.oltu.oauth2
+ org.apache.oltu.oauth2.client
+ 1.0.2
+
+
+
+ io.github.openfeign
+ feign-jackson
+ ${feign-version}
+
+
+ io.github.openfeign
+ feign-slf4j
+ ${feign-version}
+
+
+ io.github.openfeign
+ feign-core
+ ${feign-version}
+
+
+ io.github.openfeign.form
+ feign-form
+ 3.8.0
+
+
+ com.google.auth
+ google-auth-library-oauth2-http
+ 1.3.0
+
+
+
+ junit
+ junit
+ 4.13.2
+
+
+
+
+
+
+
+ com.theoryinpractise
+ googleformatter-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ ${maven-src-plugin.version}
+
+ true
+
+
+
+
+ org.codehaus.mojo
+ buildnumber-maven-plugin
+ 1.4
+
+ false
+ false
+ ${project.build.directory}/classes/catalog
+ VERSION
+
+
+
+ generate-resources
+
+ create-metadata
+
+
+
+
+
+ io.swagger.codegen.v3
+ swagger-codegen-maven-plugin
+ 3.0.16
+
+
+
+ generate
+
+
+ ${project.basedir}/../../catalog-rest-service/target/classes/assets/swagger.yaml
+ java
+ feign
+ true
+ true
+
+ true
+ src/main/java/
+
+
+
+
+
+
+
+
+
+
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/gateway/OpenMetadata.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/gateway/OpenMetadata.java
new file mode 100644
index 00000000000..e87f5681d4d
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/gateway/OpenMetadata.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.gateway;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import feign.RequestInterceptor;
+import io.swagger.client.ApiClient;
+import io.swagger.client.api.CatalogApi;
+import org.openmetadata.catalog.api.CatalogVersion;
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+import org.openmetadata.client.interceptors.CustomRequestInterceptor;
+import org.openmetadata.client.security.factory.AuthenticationProviderFactory;
+import org.openmetadata.core.util.VersionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OpenMetadata {
+ private static final Logger LOG = LoggerFactory.getLogger(OpenMetadata.class);
+ private static final CatalogVersion CATALOG_VERSION_CLIENT;
+
+ static {
+ CATALOG_VERSION_CLIENT = VersionUtils.getCatalogVersion("/catalog/VERSION");
+ }
+
+ private ApiClient apiClient;
+ private OpenMetadataServerConnection serverConfig;
+ private String basePath;
+ private final String requestInterceptorKey = "custom";
+
+ public OpenMetadata(OpenMetadataServerConnection config) {
+ serverConfig = config;
+ apiClient = new ApiClient();
+ AuthenticationProviderFactory factory = new AuthenticationProviderFactory();
+ apiClient.addAuthorization("oauth", factory.getAuthProvider(config));
+ basePath = config.getHostPort() + "/";
+ apiClient.setBasePath(basePath);
+ apiClient.getObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ validateVersion();
+ }
+
+ public T buildClient(Class clientClass) {
+ return apiClient.buildClient(clientClass);
+ }
+
+ public T buildClient(Class clientClass, Class requestClass) {
+ updateRequestType(requestClass);
+ return apiClient.buildClient(clientClass);
+ }
+
+ public void updateRequestType(Class requestClass) {
+ if (apiClient.getApiAuthorizations().containsKey(requestInterceptorKey)) {
+ apiClient.getApiAuthorizations().remove(requestInterceptorKey);
+ }
+ CustomRequestInterceptor newInterceptor =
+ new CustomRequestInterceptor(apiClient.getObjectMapper(), requestClass);
+ apiClient.addAuthorization(requestInterceptorKey, newInterceptor);
+ return;
+ }
+
+ public void addRequestInterceptor(String requestInterceptorKey, RequestInterceptor interceptor) {
+ if (apiClient.getApiAuthorizations().containsKey(requestInterceptorKey)) {
+ LOG.info("Interceptor with this key already exists");
+ return;
+ }
+ apiClient.addAuthorization(requestInterceptorKey, interceptor);
+ return;
+ }
+
+ public void validateVersion() {
+ String clientVersion = getClientVersion();
+ String serverVersion = getServerVersion();
+ if (serverVersion.equals(clientVersion)) {
+ LOG.debug("OpenMetaData Client Initialized successfully.");
+ } else {
+ LOG.error(
+ "OpenMetaData Client Failed to be Initialized successfully. Version mismatch between CLient and Server issue");
+ }
+ }
+
+ public String getServerVersion() {
+ CatalogApi api = apiClient.buildClient(CatalogApi.class);
+ io.swagger.client.model.CatalogVersion serverVersion = api.getCatalogVersion();
+ return VersionUtils.getVersionFromString(serverVersion.getVersion());
+ }
+
+ public String getClientVersion() {
+ return VersionUtils.getVersionFromString(CATALOG_VERSION_CLIENT.getVersion());
+ }
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/interceptors/CustomRequestInterceptor.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/interceptors/CustomRequestInterceptor.java
new file mode 100644
index 00000000000..72a54a20006
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/interceptors/CustomRequestInterceptor.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.interceptors;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.openmetadata.client.gateway.OpenMetadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CustomRequestInterceptor implements RequestInterceptor {
+ private static final Logger LOG = LoggerFactory.getLogger(OpenMetadata.class);
+ private final Class type;
+ ObjectMapper mapper;
+
+ public CustomRequestInterceptor(ObjectMapper iMapper, Class type) {
+ this.type = type;
+ mapper = iMapper;
+ }
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {
+ try {
+ LOG.debug("Trying to Convert from generated class to org.openmetadata");
+ String body = new String(requestTemplate.body());
+ K value = mapper.readValue(body, this.getType());
+ requestTemplate.body(mapper.writeValueAsString(value));
+ } catch (Exception ex) {
+ LOG.error("[CustomInterceptor] Failed in transforming request with exception :" + ex.getMessage());
+ }
+ }
+
+ public Class getType() {
+ return this.type;
+ }
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/interceptors/OktaAccessTokenRequestInterceptor.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/interceptors/OktaAccessTokenRequestInterceptor.java
new file mode 100644
index 00000000000..580cec08699
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/interceptors/OktaAccessTokenRequestInterceptor.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.interceptors;
+
+import feign.RequestTemplate;
+import java.util.Base64;
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+import org.openmetadata.client.model.OktaSSOConfig;
+import org.openmetadata.client.security.interfaces.AuthenticationProvider;
+
+public class OktaAccessTokenRequestInterceptor implements AuthenticationProvider {
+ private OktaSSOConfig securityConfig;
+ private String base64Credentials;
+
+ public OktaAccessTokenRequestInterceptor(OktaSSOConfig config) {
+ securityConfig = config;
+ }
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {
+ if (requestTemplate.headers().containsKey("Authorization")) {
+ return;
+ }
+ if (base64Credentials == null) {
+ this.authToken();
+ }
+ requestTemplate.header("Authorization", "Basic " + getAccessToken());
+ }
+
+ @Override
+ public AuthenticationProvider create(OpenMetadataServerConnection iConfig) {
+ return new OktaAccessTokenRequestInterceptor((OktaSSOConfig) iConfig.getSecurityConfig());
+ }
+
+ @Override
+ public String authToken() {
+ base64Credentials =
+ Base64.getEncoder()
+ .encodeToString((securityConfig.getClientId() + ":" + securityConfig.getClientSecret()).getBytes());
+ return base64Credentials;
+ }
+
+ @Override
+ public String getAccessToken() {
+ return base64Credentials;
+ }
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/model/OktaAccessTokenResponse.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/model/OktaAccessTokenResponse.java
new file mode 100644
index 00000000000..ea87902bae4
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/model/OktaAccessTokenResponse.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+public class OktaAccessTokenResponse {
+ @JsonProperty("token_type")
+ private String tokenType = null;
+
+ @JsonProperty("expires_in")
+ private Long expiresIn = null;
+
+ @JsonProperty("access_token")
+ private String accessToken = null;
+
+ @JsonProperty("scope")
+ private String scope = null;
+
+ /**
+ * Get TokenType
+ *
+ * @return TokenType
+ */
+ @Schema(description = "")
+ public String getTokenType() {
+ return tokenType;
+ }
+
+ public void setTokenType(String description) {
+ this.tokenType = description;
+ }
+
+ public OktaAccessTokenResponse withTokenType(String displayName) {
+ this.tokenType = displayName;
+ return this;
+ }
+
+ /**
+ * Get ExpiresIn
+ *
+ * @return ExpiresIn
+ */
+ @Schema(description = "")
+ public Long getExpiresIn() {
+ return expiresIn;
+ }
+
+ public void setExpiresIn(Long iExpiresIn) {
+ this.expiresIn = iExpiresIn;
+ }
+
+ public OktaAccessTokenResponse withExpiresIn(Long iExpiresIn) {
+ this.expiresIn = iExpiresIn;
+ return this;
+ }
+
+ /**
+ * Get AccessToken
+ *
+ * @return AccessToken
+ */
+ @Schema(description = "")
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ public void setAccessToken(String iAccessToken) {
+ this.accessToken = iAccessToken;
+ }
+
+ public OktaAccessTokenResponse withAccessToken(String iAccessToken) {
+ this.accessToken = iAccessToken;
+ return this;
+ }
+
+ /**
+ * Get Scope
+ *
+ * @return Scope
+ */
+ @Schema(description = "")
+ public String getScope() {
+ return scope;
+ }
+
+ public void setScope(String iScopes) {
+ this.scope = iScopes;
+ }
+
+ public OktaAccessTokenResponse withScope(String iScopes) {
+ this.scope = iScopes;
+ return this;
+ }
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/model/OktaSSOConfig.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/model/OktaSSOConfig.java
new file mode 100644
index 00000000000..6eeb2893b63
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/model/OktaSSOConfig.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class OktaSSOConfig {
+ /** Okta Client ID for the service application. (Required) */
+ private String clientId;
+ /** Okta Client Secret for the API service application. (Required) */
+ private String clientSecret;
+ /** Okta Authorization Server Url. (Required) */
+ private String authorizationServerURL;
+
+ /** Okta client scopes. */
+ private List scopes = new ArrayList();
+
+ /** Okta Client ID. (Required) */
+ public String getClientId() {
+ return clientId;
+ }
+
+ /** Okta Client ID. (Required) */
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public OktaSSOConfig withClientId(String clientId) {
+ this.clientId = clientId;
+ return this;
+ }
+
+ /** Okta Client Secret. (Required) */
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ /** Okta Client Secret. (Required) */
+ public void setClientSecret(String clientId) {
+ this.clientSecret = clientId;
+ }
+
+ public OktaSSOConfig withClientSecret(String clientId) {
+ this.clientSecret = clientId;
+ return this;
+ }
+
+ /** Okta org url. (Required) */
+ public String getAuthorizationServerURL() {
+ return authorizationServerURL;
+ }
+
+ /** Okta org url. (Required) */
+ public void setAuthorizationServerURL(String orgURL) {
+ this.authorizationServerURL = orgURL;
+ }
+
+ public OktaSSOConfig withAuthorizationServerURL(String orgURL) {
+ this.authorizationServerURL = orgURL;
+ return this;
+ }
+
+ /** Okta client scopes. */
+ public List getScopes() {
+ return scopes;
+ }
+
+ /** Okta client scopes. */
+ public void setScopes(List scopes) {
+ this.scopes = scopes;
+ }
+
+ public OktaSSOConfig withScopes(List scopes) {
+ this.scopes = scopes;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(OktaSSOConfig.class.getName())
+ .append('@')
+ .append(Integer.toHexString(System.identityHashCode(this)))
+ .append('[');
+ sb.append("clientId");
+ sb.append('=');
+ sb.append(((this.clientId == null) ? "" : this.clientId));
+ sb.append("clientSecret");
+ sb.append('=');
+ sb.append(((this.clientSecret == null) ? "" : this.clientSecret));
+ sb.append(',');
+ sb.append("authorizationServerURL");
+ sb.append('=');
+ sb.append(((this.authorizationServerURL == null) ? "" : this.authorizationServerURL));
+ sb.append(',');
+ sb.append(',');
+ sb.append("scopes");
+ sb.append('=');
+ sb.append(((this.scopes == null) ? "" : this.scopes));
+ sb.append(',');
+ if (sb.charAt((sb.length() - 1)) == ',') {
+ sb.setCharAt((sb.length() - 1), ']');
+ } else {
+ sb.append(']');
+ }
+ return sb.toString();
+ }
+
+ public enum GrantType {
+ AUTHORIZATION_CODE("authorization_code"),
+ CLIENT_CREDENTIALS("client_credentials"),
+ IMPLICIT("implicit");
+ private final String value;
+ private static final Map CONSTANTS =
+ new HashMap();
+
+ static {
+ for (OktaSSOConfig.GrantType c : values()) {
+ CONSTANTS.put(c.value, c);
+ }
+ }
+
+ GrantType(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return this.value;
+ }
+
+ public String value() {
+ return this.value;
+ }
+
+ public static OktaSSOConfig.GrantType fromValue(String value) {
+ OktaSSOConfig.GrantType constant = CONSTANTS.get(value);
+ if (constant == null) {
+ throw new IllegalArgumentException(value);
+ } else {
+ return constant;
+ }
+ }
+ }
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/Auth0AuthenticationProvider.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/Auth0AuthenticationProvider.java
new file mode 100644
index 00000000000..77c07cd66f7
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/Auth0AuthenticationProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.security;
+
+import feign.RequestTemplate;
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+import org.openmetadata.client.security.interfaces.AuthenticationProvider;
+
+public class Auth0AuthenticationProvider implements AuthenticationProvider {
+ @Override
+ public AuthenticationProvider create(OpenMetadataServerConnection iConfig) {
+ return null;
+ }
+
+ @Override
+ public String authToken() {
+ return null;
+ }
+
+ @Override
+ public String getAccessToken() {
+ return null;
+ }
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {}
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/AzureAuthenticationProvider.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/AzureAuthenticationProvider.java
new file mode 100644
index 00000000000..1014130ce6f
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/AzureAuthenticationProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.security;
+
+import feign.RequestTemplate;
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+import org.openmetadata.client.security.interfaces.AuthenticationProvider;
+
+public class AzureAuthenticationProvider implements AuthenticationProvider {
+ @Override
+ public AuthenticationProvider create(OpenMetadataServerConnection iConfig) {
+ return null;
+ }
+
+ @Override
+ public String authToken() {
+ return null;
+ }
+
+ @Override
+ public String getAccessToken() {
+ return null;
+ }
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {}
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/CustomOIDCAuthenticationProvider.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/CustomOIDCAuthenticationProvider.java
new file mode 100644
index 00000000000..654c1f5bb0f
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/CustomOIDCAuthenticationProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.security;
+
+import feign.RequestTemplate;
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+import org.openmetadata.client.security.interfaces.AuthenticationProvider;
+
+public class CustomOIDCAuthenticationProvider implements AuthenticationProvider {
+ @Override
+ public AuthenticationProvider create(OpenMetadataServerConnection iConfig) {
+ return null;
+ }
+
+ @Override
+ public String authToken() {
+ return null;
+ }
+
+ @Override
+ public String getAccessToken() {
+ return null;
+ }
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {}
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/GoogleAuthenticationProvider.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/GoogleAuthenticationProvider.java
new file mode 100644
index 00000000000..c83b7e778f9
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/GoogleAuthenticationProvider.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.security;
+
+import com.google.auth.oauth2.AccessToken;
+import com.google.auth.oauth2.IdTokenCredentials;
+import com.google.auth.oauth2.ServiceAccountCredentials;
+import feign.RequestTemplate;
+import java.io.FileInputStream;
+import java.util.Arrays;
+import org.openmetadata.catalog.security.client.GoogleSSOClientConfig;
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+import org.openmetadata.client.security.interfaces.AuthenticationProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GoogleAuthenticationProvider implements AuthenticationProvider {
+ private static final Logger LOG = LoggerFactory.getLogger(GoogleAuthenticationProvider.class);
+ private OpenMetadataServerConnection serverConfig;
+ private GoogleSSOClientConfig securityConfig;
+ private String generatedAuthToken;
+ private Long expirationTimeMillis;
+ private final String OPENID_SCOPE = "https://www.googleapis.com/auth/plus.me";
+ private final String PROFILE_SCOPE = "https://www.googleapis.com/auth/userinfo.profile";
+ private final String EMAIL_SCOPE = "https://www.googleapis.com/auth/userinfo.email";
+
+ public GoogleAuthenticationProvider(OpenMetadataServerConnection iConfig) {
+ if (!iConfig.getAuthProvider().equals(OpenMetadataServerConnection.AuthProvider.GOOGLE)) {
+ LOG.error("Required type to invoke is Google for GoogleAuthentication Provider");
+ throw new RuntimeException("Required type to invoke is Google for GoogleAuthentication Provider");
+ }
+ serverConfig = iConfig;
+
+ securityConfig = (GoogleSSOClientConfig) iConfig.getSecurityConfig();
+ if (securityConfig == null) {
+ LOG.error("Security Config is missing, it is required");
+ throw new RuntimeException("Security Config is missing, it is required");
+ }
+
+ generatedAuthToken = "";
+ }
+
+ @Override
+ public AuthenticationProvider create(OpenMetadataServerConnection iConfig) {
+ return new GoogleAuthenticationProvider(iConfig);
+ }
+
+ @Override
+ public String authToken() {
+ try {
+ String credPath = securityConfig.getSecretKey();
+ String targetAudience = securityConfig.getAudience();
+ if ((credPath != null && credPath != "") && (targetAudience != null && targetAudience != "")) {
+ ServiceAccountCredentials saCreds = ServiceAccountCredentials.fromStream(new FileInputStream(credPath));
+
+ saCreds =
+ (ServiceAccountCredentials) saCreds.createScoped(Arrays.asList(OPENID_SCOPE, PROFILE_SCOPE, EMAIL_SCOPE));
+ IdTokenCredentials tokenCredential =
+ IdTokenCredentials.newBuilder().setIdTokenProvider(saCreds).setTargetAudience(targetAudience).build();
+ AccessToken token = tokenCredential.refreshAccessToken();
+ this.expirationTimeMillis = token.getExpirationTime().getTime();
+ this.generatedAuthToken = token.getTokenValue();
+ } else {
+ LOG.error("Credentials Path or Target Audience is null");
+ }
+ } catch (Exception ex) {
+ LOG.error("Google Authentication Provider error in getting access token" + ex.getMessage());
+ }
+ return generatedAuthToken;
+ }
+
+ @Override
+ public String getAccessToken() {
+ return generatedAuthToken;
+ }
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {
+ if (requestTemplate.url().contains("version")) {
+ return;
+ }
+ if (requestTemplate.headers().containsKey("Authorization")) {
+ return;
+ }
+ // If first time, get the token
+ if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) {
+ this.authToken();
+ }
+ if (getAccessToken() != null) {
+ requestTemplate.header("Authorization", "Bearer " + getAccessToken());
+ }
+ }
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/NoOpAuthenticationProvider.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/NoOpAuthenticationProvider.java
new file mode 100644
index 00000000000..42b344818d3
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/NoOpAuthenticationProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.security;
+
+import feign.RequestTemplate;
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+import org.openmetadata.client.security.interfaces.AuthenticationProvider;
+
+public class NoOpAuthenticationProvider implements AuthenticationProvider {
+ public NoOpAuthenticationProvider() {}
+
+ @Override
+ public AuthenticationProvider create(OpenMetadataServerConnection iConfig) {
+ return new NoOpAuthenticationProvider();
+ }
+
+ @Override
+ public String authToken() {
+ return null;
+ }
+
+ @Override
+ public String getAccessToken() {
+ return "";
+ }
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {
+ // no-auth we dont apply anything
+ return;
+ }
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/OktaAuthenticationProvider.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/OktaAuthenticationProvider.java
new file mode 100644
index 00000000000..7cce0f6dd4f
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/OktaAuthenticationProvider.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.security;
+
+import feign.RequestTemplate;
+import io.swagger.client.ApiClient;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+import org.openmetadata.client.interceptors.OktaAccessTokenRequestInterceptor;
+import org.openmetadata.client.model.OktaAccessTokenResponse;
+import org.openmetadata.client.model.OktaSSOConfig;
+import org.openmetadata.client.security.interfaces.AuthenticationProvider;
+import org.openmetadata.client.security.interfaces.OktaAccessTokenApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OktaAuthenticationProvider implements AuthenticationProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GoogleAuthenticationProvider.class);
+
+ public static final String clientAssertionType = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
+ private OpenMetadataServerConnection serverConfig;
+ private OktaSSOConfig securityConfig;
+ private String generatedAuthToken;
+ private Long expirationTimeMillis;
+ private OktaAccessTokenApi oktaSSOClient;
+
+ public OktaAuthenticationProvider(OpenMetadataServerConnection iConfig) {
+ if (!iConfig.getAuthProvider().equals(OpenMetadataServerConnection.AuthProvider.OKTA)) {
+ LOG.error("Required type to invoke is OKTA for OKTA Authentication Provider");
+ throw new RuntimeException("Required type to invoke is OKTA for OKTA Authentication Provider");
+ }
+ serverConfig = iConfig;
+
+ securityConfig = (OktaSSOConfig) iConfig.getSecurityConfig();
+ if (securityConfig == null) {
+ LOG.error("Security Config is missing, it is required");
+ throw new RuntimeException("Security Config is missing, it is required");
+ }
+ generatedAuthToken = "";
+
+ // Setup Access Token Setting
+ ApiClient oktaSSO = new ApiClient();
+ oktaSSO.setBasePath(securityConfig.getAuthorizationServerURL());
+ OktaAccessTokenRequestInterceptor interceptor = new OktaAccessTokenRequestInterceptor(securityConfig);
+ oktaSSO.addAuthorization("OAuthToken", interceptor);
+ oktaSSOClient = oktaSSO.buildClient(OktaAccessTokenApi.class);
+ }
+
+ @Override
+ public AuthenticationProvider create(OpenMetadataServerConnection iConfig) {
+ return new OktaAuthenticationProvider(iConfig);
+ }
+
+ @Override
+ public String authToken() {
+ OktaAccessTokenResponse resp = oktaSSOClient.getAccessToken("client_credentials", "test");
+ generatedAuthToken = resp.getAccessToken();
+ expirationTimeMillis = Date.from(Instant.now().plus(resp.getExpiresIn(), ChronoUnit.SECONDS)).getTime();
+ return generatedAuthToken;
+ }
+
+ @Override
+ public String getAccessToken() {
+ return generatedAuthToken;
+ }
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {
+ if (requestTemplate.url().contains("version")) {
+ return;
+ }
+ if (requestTemplate.headers().containsKey("Authorization")) {
+ return;
+ }
+ // If first time, get the token
+ if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) {
+ this.authToken();
+ }
+
+ if (getAccessToken() != null) {
+ requestTemplate.header("Authorization", "Bearer " + getAccessToken());
+ }
+ }
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/OpenMetadataAuthenticationProvider.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/OpenMetadataAuthenticationProvider.java
new file mode 100644
index 00000000000..a928452e63f
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/OpenMetadataAuthenticationProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.security;
+
+import feign.RequestTemplate;
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+import org.openmetadata.client.security.interfaces.AuthenticationProvider;
+
+public class OpenMetadataAuthenticationProvider implements AuthenticationProvider {
+ @Override
+ public AuthenticationProvider create(OpenMetadataServerConnection iConfig) {
+ return null;
+ }
+
+ @Override
+ public String authToken() {
+ return null;
+ }
+
+ @Override
+ public String getAccessToken() {
+ return null;
+ }
+
+ @Override
+ public void apply(RequestTemplate requestTemplate) {}
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/factory/AuthenticationProviderFactory.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/factory/AuthenticationProviderFactory.java
new file mode 100644
index 00000000000..f2ff2b27084
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/factory/AuthenticationProviderFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.security.factory;
+
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+import org.openmetadata.client.security.GoogleAuthenticationProvider;
+import org.openmetadata.client.security.NoOpAuthenticationProvider;
+import org.openmetadata.client.security.OktaAuthenticationProvider;
+import org.openmetadata.client.security.interfaces.AuthenticationProvider;
+
+public class AuthenticationProviderFactory {
+ public AuthenticationProvider getAuthProvider(OpenMetadataServerConnection serverConfig) {
+ switch (serverConfig.getAuthProvider()) {
+ case NO_AUTH:
+ return new NoOpAuthenticationProvider();
+ case GOOGLE:
+ return new GoogleAuthenticationProvider(serverConfig);
+ case OKTA:
+ return new OktaAuthenticationProvider(serverConfig);
+ case AUTH_0:
+ case CUSTOM_OIDC:
+ case AZURE:
+ case OPENMETADATA:
+ return null;
+ }
+ return null;
+ }
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/interfaces/AuthenticationProvider.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/interfaces/AuthenticationProvider.java
new file mode 100644
index 00000000000..1f83aaf37ee
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/interfaces/AuthenticationProvider.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.security.interfaces;
+
+import feign.RequestInterceptor;
+import org.openmetadata.catalog.services.connections.metadata.OpenMetadataServerConnection;
+
+public interface AuthenticationProvider extends RequestInterceptor {
+ AuthenticationProvider create(OpenMetadataServerConnection iConfig);
+
+ String authToken();
+
+ String getAccessToken();
+}
diff --git a/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/interfaces/OktaAccessTokenApi.java b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/interfaces/OktaAccessTokenApi.java
new file mode 100644
index 00000000000..97c0320379f
--- /dev/null
+++ b/openmetadata-clients/openmetadata-java-client/src/main/java/org/openmetadata/client/security/interfaces/OktaAccessTokenApi.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openmetadata.client.security.interfaces;
+
+import feign.*;
+import io.swagger.client.ApiClient;
+import java.util.Map;
+import org.openmetadata.client.model.OktaAccessTokenResponse;
+
+public interface OktaAccessTokenApi extends ApiClient.Api {
+ @RequestLine(
+ "POST /v1/token?grant_type={grant_type}&scope={scope}&client_assertion_type={client_assertion_type}&client_assertion={client_assertion}")
+ @Headers({
+ "Content-Type: application/x-www-form-urlencoded",
+ "Accept: application/json",
+ })
+ OktaAccessTokenResponse getAccessToken(
+ @Param("grant_type") String grant_type,
+ @Param("scope") String scope,
+ @Param("client_assertion_type") String client_assertion_type,
+ @Param("client_assertion") String client_assertion);
+
+ @RequestLine(
+ "POST /v1/token?grant_type={grant_type}&scope={scope}&client_assertion_type={client_assertion_type}&client_assertion={client_assertion}")
+ @Headers({
+ "Content-Type: application/x-www-form-urlencoded",
+ "Accept: application/json",
+ })
+ OktaAccessTokenResponse getAccessToken(@QueryMap(encoded = true) Map queryParams);
+
+ @RequestLine("POST /v1/token?grant_type={grant_type}&scope={scope}")
+ @Headers({
+ "Content-Type: application/x-www-form-urlencoded",
+ "Accept: application/json",
+ })
+ OktaAccessTokenResponse getAccessToken(@Param("grant_type") String grant_type, @Param("scope") String scope);
+}
diff --git a/openmetadata-clients/pom.xml b/openmetadata-clients/pom.xml
new file mode 100644
index 00000000000..39b95f7d1f1
--- /dev/null
+++ b/openmetadata-clients/pom.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ catalog
+ org.openmetadata
+ 0.11.0-SNAPSHOT
+
+ 4.0.0
+
+ openmetadata-clients
+ pom
+
+ openmetadata-java-client
+
+
+ 11
+ 11
+
+
diff --git a/openmetadata-core/src/main/java/org/openmetadata/core/util/VersionUtils.java b/openmetadata-core/src/main/java/org/openmetadata/core/util/VersionUtils.java
new file mode 100644
index 00000000000..caaf2fb9ce4
--- /dev/null
+++ b/openmetadata-core/src/main/java/org/openmetadata/core/util/VersionUtils.java
@@ -0,0 +1,40 @@
+package org.openmetadata.core.util;
+
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.regex.Pattern;
+import org.openmetadata.catalog.api.CatalogVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class VersionUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(CommonUtil.class);
+
+ private VersionUtils() {}
+
+ public static CatalogVersion getCatalogVersion(String resourceName) {
+ CatalogVersion catalogVersion = new CatalogVersion();
+ try {
+ InputStream fileInput = VersionUtils.class.getResourceAsStream(resourceName);
+ Properties props = new Properties();
+ props.load(fileInput);
+ catalogVersion.setVersion(props.getProperty("version", "unknown"));
+ catalogVersion.setRevision(props.getProperty("revision", "unknown"));
+
+ String timestampAsString = props.getProperty("timestamp");
+ Long timestamp = timestampAsString != null ? Long.valueOf(timestampAsString) : null;
+ catalogVersion.setTimestamp(timestamp);
+ } catch (Exception ie) {
+ LOG.warn("Failed to read catalog version file");
+ }
+ return catalogVersion;
+ }
+
+ public static String getVersionFromString(String input) {
+ if (input.contains("-")) {
+ return input.split(Pattern.quote("-"))[0];
+ } else {
+ throw new IllegalArgumentException("Invalid Version Given :" + input);
+ }
+ }
+}