Skip to content

Commit

Permalink
Bugfix: timeout error when listing Consumption Roles (data-dot-all#1303)
Browse files Browse the repository at this point in the history
### Feature or Bugfix
- Bugfix


### Detail
- as GraphQL resolvers are 'lazy', for ShareRequest Modal window we
simply don't fetch the managedPolicy property -- no timeout
- managed policies are fetched, when consumption role is selected from
dropdown

### Relates
- data-dot-all#1288 

### Security
Please answer the questions below briefly where applicable, or write
`N/A`. Based on
[OWASP 10](https://owasp.org/Top10/en/).

- Does this PR introduce or modify any input fields or queries - this
includes
fetching data from storage outside the application (e.g. a database, an
S3 bucket)?
  - Is the input sanitized?
- What precautions are you taking before deserializing the data you
consume?
  - Is injection prevented by parametrizing queries?
  - Have you ensured no `eval` or similar functions are used?
- Does this PR introduce any functionality or component that requires
authorization?
- How have you ensured it respects the existing AuthN/AuthZ mechanisms?
  - Are you logging failed auth attempts?
- Are you using or adding any cryptographic features?
  - Do you use a standard proven implementations?
  - Are the used keys controlled by the customer? Where are they stored?
- Are you introducing any new policies/roles/users?
  - Have you used the least-privilege principle? How?


By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license.

---------

Co-authored-by: Sofia Sazonova <[email protected]>
  • Loading branch information
SofiaSazonova and Sofia Sazonova authored May 31, 2024
1 parent 6c59e9d commit 0cc6f23
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 33 deletions.
20 changes: 18 additions & 2 deletions backend/dataall/core/environment/api/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@
list_environments,
list_groups,
list_valid_environments,
get_consumption_role_policies,
)
from dataall.core.environment.api.types import (
Environment,
EnvironmentSearchResult,
EnvironmentSimplifiedSearchResult,
RoleManagedPolicy,
)
from dataall.core.environment.api.types import Environment, EnvironmentSearchResult, EnvironmentSimplifiedSearchResult


getTrustAccount = gql.QueryField(
name='getTrustAccount',
Expand Down Expand Up @@ -204,3 +209,14 @@
resolver=get_pivot_role_name,
test_scope='Environment',
)

getConsumptionRolePolicies = gql.QueryField(
name='getConsumptionRolePolicies',
args=[
gql.Argument(name='environmentUri', type=gql.NonNullableType(gql.String)),
gql.Argument(name='IAMRoleName', type=gql.NonNullableType(gql.String)),
],
type=gql.ArrayType(RoleManagedPolicy),
resolver=get_consumption_role_policies,
test_scope='Environment',
)
19 changes: 10 additions & 9 deletions backend/dataall/core/environment/api/resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,16 @@ def get_parent_organization(context: Context, source, **kwargs):
return org


def get_policies(context: Context, source, **kwargs):
environment = EnvironmentService.find_environment_by_uri(uri=source.environmentUri)
return PolicyManager(
role_name=source.IAMRoleName,
environmentUri=environment.environmentUri,
account=environment.AwsAccountId,
region=environment.region,
resource_prefix=environment.resourcePrefix,
).get_all_policies()
# used from ConsumptionRole type as field resolver
def resolve_consumption_role_policies(context: Context, source, **kwargs):
return EnvironmentService.resolve_consumption_role_policies(
uri=source.environmentUri, IAMRoleName=source.IAMRoleName
)


# used from getConsumptionRolePolicies query -- query resolver
def get_consumption_role_policies(context: Context, source, environmentUri, IAMRoleName):
return EnvironmentService.resolve_consumption_role_policies(uri=environmentUri, IAMRoleName=IAMRoleName)


def resolve_environment_networks(context: Context, source, **kwargs):
Expand Down
6 changes: 4 additions & 2 deletions backend/dataall/core/environment/api/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from dataall.core.environment.api.resolvers import (
get_environment_stack,
get_parent_organization,
get_policies,
resolve_consumption_role_policies,
resolve_environment_networks,
resolve_parameters,
resolve_user_role,
Expand Down Expand Up @@ -180,7 +180,9 @@
gql.Field(name='created', type=gql.String),
gql.Field(name='updated', type=gql.String),
gql.Field(name='deleted', type=gql.String),
gql.Field(name='managedPolicies', type=gql.ArrayType(RoleManagedPolicy), resolver=get_policies),
gql.Field(
name='managedPolicies', type=gql.ArrayType(RoleManagedPolicy), resolver=resolve_consumption_role_policies
),
],
)

Expand Down
12 changes: 12 additions & 0 deletions backend/dataall/core/environment/services/environment_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -1115,3 +1115,15 @@ def get_template_from_resource_bucket(organization_uri, template_name):
)

return S3_client.get_presigned_url(region, resource_bucket, template_key)

@staticmethod
@ResourcePolicyService.has_resource_permission(environment_permissions.GET_ENVIRONMENT)
def resolve_consumption_role_policies(uri, IAMRoleName):
environment = EnvironmentService.find_environment_by_uri(uri=uri)
return PolicyManager(
role_name=IAMRoleName,
environmentUri=uri,
account=environment.AwsAccountId,
region=environment.region,
resource_prefix=environment.resourcePrefix,
).get_all_policies()
62 changes: 47 additions & 15 deletions frontend/src/modules/Catalog/components/RequestAccessModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
listEnvironmentGroups,
listValidEnvironments,
requestDashboardShare,
getConsumptionRolePolicies,
useClient
} from 'services';
import { useNavigate } from 'react-router-dom';
Expand All @@ -41,6 +42,8 @@ export const RequestAccessModal = (props) => {
const [groupOptions, setGroupOptions] = useState([]);
const [loadingRoles, setLoadingRoles] = useState(false);
const [roleOptions, setRoleOptions] = useState([]);
const [isSharePolicyAttached, setIsSharePolicyAttached] = useState(true);
const [policyName, setPolicyName] = useState('');

const fetchEnvironments = useCallback(async () => {
setLoadingEnvs(true);
Expand Down Expand Up @@ -109,13 +112,8 @@ export const RequestAccessModal = (props) => {
response.data.listEnvironmentConsumptionRoles.nodes.map((g) => ({
value: g.consumptionRoleUri,
label: [g.consumptionRoleName, ' [', g.IAMRoleArn, ']'].join(''),
dataallManaged: g.dataallManaged,
isSharePolicyAttached: g.managedPolicies.find(
(policy) => policy.policy_type === 'SharePolicy'
).attached,
policyName: g.managedPolicies.find(
(policy) => policy.policy_type === 'SharePolicy'
).policy_name
IAMRoleName: g.IAMRoleName,
dataallManaged: g.dataallManaged
}))
);
} else {
Expand All @@ -128,6 +126,35 @@ export const RequestAccessModal = (props) => {
}
};

const fetchRolePolicies = async (environmentUri, IAMRoleName) => {
setLoadingRoles(true);
try {
const response = await client.query(
getConsumptionRolePolicies({
environmentUri,
IAMRoleName
})
);
if (!response.errors) {
var isSharePolicyAttached =
response.data.getConsumptionRolePolicies.find(
(policy) => policy.policy_type === 'SharePolicy'
).attached;
setIsSharePolicyAttached(isSharePolicyAttached);
var policyName = response.data.getConsumptionRolePolicies.find(
(policy) => policy.policy_type === 'SharePolicy'
).policy_name;
setPolicyName(policyName);
} else {
dispatch({ type: SET_ERROR, error: response.errors[0].message });
}
} catch (e) {
dispatch({ type: SET_ERROR, error: e.message });
} finally {
setLoadingRoles(false);
}
};

useEffect(() => {
if (client && open) {
fetchEnvironments().catch((e) =>
Expand Down Expand Up @@ -435,6 +462,15 @@ export const RequestAccessModal = (props) => {
'consumptionRoleObj',
event.target.value
);
fetchRolePolicies(
values.environment.environmentUri,
event.target.value.IAMRoleName
).catch((e) =>
dispatch({
type: SET_ERROR,
error: e.message
})
);
}}
select
value={values.consumptionRoleObj}
Expand Down Expand Up @@ -468,10 +504,9 @@ export const RequestAccessModal = (props) => {
</CardContent>
</Box>
)}

{!values.consumptionRole ||
values.consumptionRoleObj.dataallManaged ||
values.consumptionRoleObj.isSharePolicyAttached ? (
isSharePolicyAttached ? (
<Box />
) : (
<CardContent sx={{ ml: 2 }}>
Expand All @@ -496,16 +531,13 @@ export const RequestAccessModal = (props) => {
{values.consumptionRoleObj &&
!(
values.consumptionRoleObj.dataallManaged ||
values.consumptionRoleObj.isSharePolicyAttached ||
isSharePolicyAttached ||
values.attachMissingPolicies
) ? (
<FormHelperText error>
Selected consumption role is managed by
customer, but the share policy{' '}
<strong>
{values.consumptionRoleObj.policyName}
</strong>{' '}
is not attached.
<strong>{policyName}</strong> is not attached.
<br />
Please attach it or let Data.all attach it for
you.
Expand Down Expand Up @@ -556,7 +588,7 @@ export const RequestAccessModal = (props) => {
(values.consumptionRoleObj &&
!(
values.consumptionRoleObj.dataallManaged ||
values.consumptionRoleObj.isSharePolicyAttached ||
isSharePolicyAttached ||
values.attachMissingPolicies
))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { gql } from 'apollo-boost';

export const getConsumptionRolePolicies = ({
environmentUri,
IAMRoleName
}) => ({
variables: {
environmentUri,
IAMRoleName
},
query: gql`
query getConsumptionRolePolicies(
$environmentUri: String!
$IAMRoleName: String!
) {
getConsumptionRolePolicies(
environmentUri: $environmentUri
IAMRoleName: $IAMRoleName
) {
policy_type
policy_name
attached
exists
}
}
`
});
1 change: 1 addition & 0 deletions frontend/src/services/graphql/Environment/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './listEnvironmentGroups';
export * from './listEnvironments';
export * from './listValidEnvironments';
export * from './searchEnvironmentDataItems';
export * from './getConsumptionRolePolicy';
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,8 @@ export const listEnvironmentConsumptionRoles = ({
environmentUri
groupUri
IAMRoleArn
IAMRoleName
dataallManaged
managedPolicies {
policy_type
policy_name
attached
}
}
}
}
Expand Down

0 comments on commit 0cc6f23

Please sign in to comment.