fix(ui): Display warning in UI when metadata service auth is disabled. (#4728)

This commit is contained in:
John Joyce 2022-04-22 12:09:05 -07:00 committed by GitHub
parent 325c9b0f08
commit b38d14fa67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 3 deletions

View File

@ -1,5 +1,6 @@
package com.linkedin.datahub.graphql; package com.linkedin.datahub.graphql;
import com.datahub.authentication.AuthenticationConfiguration;
import com.datahub.authentication.token.TokenService; import com.datahub.authentication.token.TokenService;
import com.datahub.authorization.AuthorizationConfiguration; import com.datahub.authorization.AuthorizationConfiguration;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -221,6 +222,7 @@ public class GmsGraphQLEngine {
private final TimeseriesAspectService timeseriesAspectService; private final TimeseriesAspectService timeseriesAspectService;
private final IngestionConfiguration ingestionConfiguration; private final IngestionConfiguration ingestionConfiguration;
private final AuthenticationConfiguration authenticationConfiguration;
private final AuthorizationConfiguration authorizationConfiguration; private final AuthorizationConfiguration authorizationConfiguration;
private final VisualConfiguration visualConfiguration; private final VisualConfiguration visualConfiguration;
@ -288,6 +290,7 @@ public class GmsGraphQLEngine {
null, null,
null, null,
null, null,
null,
false, false,
null); null);
} }
@ -304,6 +307,7 @@ public class GmsGraphQLEngine {
final EntityRegistry entityRegistry, final EntityRegistry entityRegistry,
final SecretService secretService, final SecretService secretService,
final IngestionConfiguration ingestionConfiguration, final IngestionConfiguration ingestionConfiguration,
final AuthenticationConfiguration authenticationConfiguration,
final AuthorizationConfiguration authorizationConfiguration, final AuthorizationConfiguration authorizationConfiguration,
final GitVersion gitVersion, final GitVersion gitVersion,
final boolean supportsImpactAnalysis, final boolean supportsImpactAnalysis,
@ -325,6 +329,7 @@ public class GmsGraphQLEngine {
this.timeseriesAspectService = timeseriesAspectService; this.timeseriesAspectService = timeseriesAspectService;
this.ingestionConfiguration = Objects.requireNonNull(ingestionConfiguration); this.ingestionConfiguration = Objects.requireNonNull(ingestionConfiguration);
this.authenticationConfiguration = Objects.requireNonNull(authenticationConfiguration);
this.authorizationConfiguration = Objects.requireNonNull(authorizationConfiguration); this.authorizationConfiguration = Objects.requireNonNull(authorizationConfiguration);
this.visualConfiguration = visualConfiguration; this.visualConfiguration = visualConfiguration;
@ -562,6 +567,7 @@ public class GmsGraphQLEngine {
.dataFetcher("appConfig", .dataFetcher("appConfig",
new AppConfigResolver(gitVersion, analyticsService != null, new AppConfigResolver(gitVersion, analyticsService != null,
this.ingestionConfiguration, this.ingestionConfiguration,
this.authenticationConfiguration,
this.authorizationConfiguration, this.authorizationConfiguration,
supportsImpactAnalysis, this.visualConfiguration)) supportsImpactAnalysis, this.visualConfiguration))
.dataFetcher("me", new AuthenticatedResolver<>( .dataFetcher("me", new AuthenticatedResolver<>(

View File

@ -1,9 +1,11 @@
package com.linkedin.datahub.graphql.resolvers.config; package com.linkedin.datahub.graphql.resolvers.config;
import com.datahub.authentication.AuthenticationConfiguration;
import com.datahub.authorization.AuthorizationConfiguration; import com.datahub.authorization.AuthorizationConfiguration;
import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.generated.AnalyticsConfig; import com.linkedin.datahub.graphql.generated.AnalyticsConfig;
import com.linkedin.datahub.graphql.generated.AppConfig; import com.linkedin.datahub.graphql.generated.AppConfig;
import com.linkedin.datahub.graphql.generated.AuthConfig;
import com.linkedin.datahub.graphql.generated.EntityType; import com.linkedin.datahub.graphql.generated.EntityType;
import com.linkedin.datahub.graphql.generated.IdentityManagementConfig; import com.linkedin.datahub.graphql.generated.IdentityManagementConfig;
import com.linkedin.datahub.graphql.generated.LineageConfig; import com.linkedin.datahub.graphql.generated.LineageConfig;
@ -28,6 +30,7 @@ public class AppConfigResolver implements DataFetcher<CompletableFuture<AppConfi
private final GitVersion _gitVersion; private final GitVersion _gitVersion;
private final boolean _isAnalyticsEnabled; private final boolean _isAnalyticsEnabled;
private final IngestionConfiguration _ingestionConfiguration; private final IngestionConfiguration _ingestionConfiguration;
private final AuthenticationConfiguration _authenticationConfiguration;
private final AuthorizationConfiguration _authorizationConfiguration; private final AuthorizationConfiguration _authorizationConfiguration;
private final boolean _supportsImpactAnalysis; private final boolean _supportsImpactAnalysis;
private final VisualConfiguration _visualConfiguration; private final VisualConfiguration _visualConfiguration;
@ -36,12 +39,14 @@ public class AppConfigResolver implements DataFetcher<CompletableFuture<AppConfi
final GitVersion gitVersion, final GitVersion gitVersion,
final boolean isAnalyticsEnabled, final boolean isAnalyticsEnabled,
final IngestionConfiguration ingestionConfiguration, final IngestionConfiguration ingestionConfiguration,
final AuthenticationConfiguration authenticationConfiguration,
final AuthorizationConfiguration authorizationConfiguration, final AuthorizationConfiguration authorizationConfiguration,
final boolean supportsImpactAnalysis, final boolean supportsImpactAnalysis,
final VisualConfiguration visualConfiguration) { final VisualConfiguration visualConfiguration) {
_gitVersion = gitVersion; _gitVersion = gitVersion;
_isAnalyticsEnabled = isAnalyticsEnabled; _isAnalyticsEnabled = isAnalyticsEnabled;
_ingestionConfiguration = ingestionConfiguration; _ingestionConfiguration = ingestionConfiguration;
_authenticationConfiguration = authenticationConfiguration;
_authorizationConfiguration = authorizationConfiguration; _authorizationConfiguration = authorizationConfiguration;
_supportsImpactAnalysis = supportsImpactAnalysis; _supportsImpactAnalysis = supportsImpactAnalysis;
_visualConfiguration = visualConfiguration; _visualConfiguration = visualConfiguration;
@ -63,6 +68,9 @@ public class AppConfigResolver implements DataFetcher<CompletableFuture<AppConfi
final AnalyticsConfig analyticsConfig = new AnalyticsConfig(); final AnalyticsConfig analyticsConfig = new AnalyticsConfig();
analyticsConfig.setEnabled(_isAnalyticsEnabled); analyticsConfig.setEnabled(_isAnalyticsEnabled);
final AuthConfig authConfig = new AuthConfig();
authConfig.setTokenAuthEnabled(_authenticationConfiguration.isEnabled());
final PoliciesConfig policiesConfig = new PoliciesConfig(); final PoliciesConfig policiesConfig = new PoliciesConfig();
policiesConfig.setEnabled(_authorizationConfiguration.getDefaultAuthorizer().isEnabled()); policiesConfig.setEnabled(_authorizationConfiguration.getDefaultAuthorizer().isEnabled());
@ -82,11 +90,12 @@ public class AppConfigResolver implements DataFetcher<CompletableFuture<AppConfi
final ManagedIngestionConfig ingestionConfig = new ManagedIngestionConfig(); final ManagedIngestionConfig ingestionConfig = new ManagedIngestionConfig();
ingestionConfig.setEnabled(_ingestionConfiguration.isEnabled()); ingestionConfig.setEnabled(_ingestionConfiguration.isEnabled());
appConfig.setAuthConfig(authConfig);
appConfig.setAnalyticsConfig(analyticsConfig); appConfig.setAnalyticsConfig(analyticsConfig);
appConfig.setPoliciesConfig(policiesConfig); appConfig.setPoliciesConfig(policiesConfig);
appConfig.setIdentityManagementConfig(identityManagementConfig); appConfig.setIdentityManagementConfig(identityManagementConfig);
appConfig.setManagedIngestionConfig(ingestionConfig); appConfig.setManagedIngestionConfig(ingestionConfig);
appConfig.setAuthConfig(authConfig);
appConfig.setVisualConfig(_visualConfiguration); appConfig.setVisualConfig(_visualConfiguration);
return CompletableFuture.completedFuture(appConfig); return CompletableFuture.completedFuture(appConfig);

View File

@ -78,6 +78,11 @@ type AppConfig {
""" """
appVersion: String appVersion: String
"""
Auth-related configurations
"""
authConfig: AuthConfig!
""" """
Configurations related to the Analytics Feature Configurations related to the Analytics Feature
""" """
@ -139,6 +144,17 @@ type AnalyticsConfig {
enabled: Boolean! enabled: Boolean!
} }
"""
Configurations related to auth
"""
type AuthConfig {
"""
Whether token-based auth is enabled.
"""
tokenAuthEnabled: Boolean!
}
""" """
Configurations related to the Policies Feature Configurations related to the Policies Feature
""" """

View File

@ -1,6 +1,8 @@
import { Button, Divider, Select, Typography } from 'antd'; import { InfoCircleOutlined } from '@ant-design/icons';
import { Alert, Button, Divider, Select, Typography } from 'antd';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { useAppConfigQuery } from '../../graphql/app.generated';
import { useGetAccessTokenLazyQuery } from '../../graphql/auth.generated'; import { useGetAccessTokenLazyQuery } from '../../graphql/auth.generated';
import { AccessTokenDuration, AccessTokenType } from '../../types.generated'; import { AccessTokenDuration, AccessTokenType } from '../../types.generated';
import { useGetAuthenticatedUser } from '../useGetAuthenticatedUser'; import { useGetAuthenticatedUser } from '../useGetAuthenticatedUser';
@ -32,6 +34,16 @@ const ExpirationSelectConainer = styled.div`
padding-bottom: 12px; padding-bottom: 12px;
`; `;
const StyledAlert = styled(Alert)`
padding-top: 12px;
padding-bottom: 12px;
margin-bottom: 20px;
`;
const StyledInfoCircleOutlined = styled(InfoCircleOutlined)`
margin-right: 8px;
`;
const ExpirationDurationSelect = styled(Select)` const ExpirationDurationSelect = styled(Select)`
&& { && {
width: 120px; width: 120px;
@ -51,7 +63,9 @@ export const AccessTokens = () => {
const [showModal, setShowModal] = useState(false); const [showModal, setShowModal] = useState(false);
const [selectedTokenDuration, setSelectedTokenDuration] = useState(ACCESS_TOKEN_DURATIONS[0].duration); const [selectedTokenDuration, setSelectedTokenDuration] = useState(ACCESS_TOKEN_DURATIONS[0].duration);
const authenticatedUser = useGetAuthenticatedUser(); const authenticatedUser = useGetAuthenticatedUser();
const canGeneratePersonalAccessTokens = authenticatedUser?.platformPrivileges.generatePersonalAccessTokens; const isTokenAuthEnabled = useAppConfigQuery().data?.appConfig?.authConfig?.tokenAuthEnabled;
const canGeneratePersonalAccessTokens =
isTokenAuthEnabled && authenticatedUser?.platformPrivileges.generatePersonalAccessTokens;
const currentUserUrn = authenticatedUser?.corpUser.urn; const currentUserUrn = authenticatedUser?.corpUser.urn;
const [getAccessToken, { data, error }] = useGetAccessTokenLazyQuery({ const [getAccessToken, { data, error }] = useGetAccessTokenLazyQuery({
@ -94,6 +108,18 @@ export const AccessTokens = () => {
Manage Access Tokens for use with DataHub APIs. Manage Access Tokens for use with DataHub APIs.
</Typography.Paragraph> </Typography.Paragraph>
<Divider /> <Divider />
{isTokenAuthEnabled === false && (
<StyledAlert
type="error"
message={
<span>
<StyledInfoCircleOutlined />
Token based authentication is currently disabled. Contact your DataHub administrator to
enable this feature.
</span>
}
/>
)}
<Typography.Title level={5}>Personal Access Tokens</Typography.Title> <Typography.Title level={5}>Personal Access Tokens</Typography.Title>
<PersonTokenDescriptionText type="secondary"> <PersonTokenDescriptionText type="secondary">
Personal Access Tokens allow you to make programmatic requests to DataHub&apos;s APIs. They inherit your Personal Access Tokens allow you to make programmatic requests to DataHub&apos;s APIs. They inherit your

View File

@ -22,6 +22,9 @@ export const DEFAULT_APP_CONFIG = {
visualConfig: { visualConfig: {
logoUrl: undefined, logoUrl: undefined,
}, },
authConfig: {
tokenAuthEnabled: false,
},
}; };
export const AppConfigContext = React.createContext<{ export const AppConfigContext = React.createContext<{

View File

@ -22,6 +22,9 @@ query appConfig {
analyticsConfig { analyticsConfig {
enabled enabled
} }
authConfig {
tokenAuthEnabled
}
identityManagementConfig { identityManagementConfig {
enabled enabled
} }

View File

@ -116,6 +116,7 @@ public class GraphQLEngineFactory {
_entityRegistry, _entityRegistry,
_secretService, _secretService,
_configProvider.getIngestion(), _configProvider.getIngestion(),
_configProvider.getAuthentication(),
_configProvider.getAuthorization(), _configProvider.getAuthorization(),
_gitVersion, _gitVersion,
_graphService.supportsMultiHop(), _graphService.supportsMultiHop(),
@ -134,6 +135,7 @@ public class GraphQLEngineFactory {
_entityRegistry, _entityRegistry,
_secretService, _secretService,
_configProvider.getIngestion(), _configProvider.getIngestion(),
_configProvider.getAuthentication(),
_configProvider.getAuthorization(), _configProvider.getAuthorization(),
_gitVersion, _gitVersion,
_graphService.supportsMultiHop(), _graphService.supportsMultiHop(),