Skip to content

Commit

Permalink
adding update consumption role capability (#1020)
Browse files Browse the repository at this point in the history
### Feature or Bugfix

- Feature


### Detail
- Add capability to update consumption role owner and name
- Setting the paradigm to use [DataGrid (with edit/CRUD
ops)](https://v5.mui.com/x/react-data-grid/editing/#full-featured-crud-component)
instead of Table

### Relates
- Resolves #870 

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

### Testing

Tested with multiple accounts and roles
* Locally
* AWS account
* Added unit-tests
* Mocked the entire `sts` client as the tests were sending request to
AWS

- 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: Petros Kalos <kalosp@amazon.com>
  • Loading branch information
petrkalos and petrkalos authored Feb 7, 2024
1 parent 2375ba3 commit d86c07f
Show file tree
Hide file tree
Showing 14 changed files with 449 additions and 99 deletions.
8 changes: 8 additions & 0 deletions backend/dataall/core/environment/api/input_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,11 @@ class EnvironmentSortField(GraphQLEnumMapper):
gql.Argument(name='groupUri', type=gql.String),
],
)

UpdateConsumptionRoleInput = gql.InputType(
name='UpdateConsumptionRoleInput',
arguments=[
gql.Argument('consumptionRoleName', gql.String),
gql.Argument('groupUri', gql.String),
],
)
14 changes: 13 additions & 1 deletion backend/dataall/core/environment/api/mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
NewEnvironmentInput,
EnableDataSubscriptionsInput,
InviteGroupOnEnvironmentInput,
AddConsumptionRoleToEnvironmentInput
AddConsumptionRoleToEnvironmentInput,
UpdateConsumptionRoleInput,
)
from dataall.core.environment.api.resolvers import *

Expand Down Expand Up @@ -110,3 +111,14 @@
resolver=disable_subscriptions,
type=gql.Boolean,
)

updateConsumptionRole = gql.MutationField(
name='updateConsumptionRole',
args=[
gql.Argument('environmentUri', type=gql.NonNullableType(gql.String)),
gql.Argument('consumptionRoleUri', type=gql.NonNullableType(gql.String)),
gql.Argument('input', type=UpdateConsumptionRoleInput),
],
type=gql.Ref('ConsumptionRole'),
resolver=update_consumption_role,
)
11 changes: 11 additions & 0 deletions backend/dataall/core/environment/api/resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,17 @@ def remove_consumption_role(context: Context, source, environmentUri=None, consu
return status


def update_consumption_role(context: Context, source, environmentUri=None, consumptionRoleUri=None, input={}):
with context.engine.scoped_session() as session:
consumption_role = EnvironmentService.update_consumption_role(
session=session,
uri=consumptionRoleUri,
env_uri=environmentUri,
input=input,
)
return consumption_role


def list_environment_invited_groups(
context: Context, source, environmentUri=None, filter=None
):
Expand Down
31 changes: 28 additions & 3 deletions backend/dataall/core/environment/services/environment_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,31 @@ def remove_consumption_role(session, uri, env_uri):
)
return True

@staticmethod
@has_tenant_permission(permissions.MANAGE_ENVIRONMENTS)
@has_resource_permission(permissions.REMOVE_ENVIRONMENT_CONSUMPTION_ROLE)
def update_consumption_role(session, uri, env_uri, input):
if not input:
raise exceptions.RequiredParameter('input')
if not input.get('groupUri'):
raise exceptions.RequiredParameter('groupUri')
if not input.get('consumptionRoleName'):
raise exceptions.RequiredParameter('consumptionRoleName')
consumption_role = EnvironmentService.get_environment_consumption_role(session, uri, env_uri)
if consumption_role:
ResourcePolicy.update_resource_policy(
session=session,
resource_uri=uri,
resource_type=ConsumptionRole.__name__,
old_group=consumption_role.groupUri,
new_group=input['groupUri'],
new_permissions=permissions.CONSUMPTION_ROLE_ALL
)
for key, value in input.items():
setattr(consumption_role, key, value)
session.commit()
return consumption_role

@staticmethod
def query_user_environments(session, username, groups, filter) -> Query:
query = (
Expand Down Expand Up @@ -699,7 +724,7 @@ def query_user_environment_consumption_roles(session, groups, uri, filter) -> Qu
ConsumptionRole.groupUri == group,
)
)
return query
return query.order_by(ConsumptionRole.consumptionRoleUri)

@staticmethod
@has_resource_permission(permissions.LIST_ENVIRONMENT_CONSUMPTION_ROLES)
Expand Down Expand Up @@ -731,7 +756,7 @@ def query_all_environment_consumption_roles(session, uri, filter) -> Query:
ConsumptionRole.groupUri == group,
)
)
return query
return query.order_by(ConsumptionRole.consumptionRoleUri)

@staticmethod
@has_resource_permission(permissions.LIST_ENVIRONMENT_CONSUMPTION_ROLES)
Expand Down Expand Up @@ -817,7 +842,7 @@ def get_environment_group(session, group_uri, environment_uri):
return env_group

@staticmethod
def get_environment_consumption_role(session, role_uri, environment_uri):
def get_environment_consumption_role(session, role_uri, environment_uri) -> ConsumptionRole:
role = (
session.query(ConsumptionRole)
.filter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,29 @@ def find_resource_policy(
)
return resource_policy

@staticmethod
def update_resource_policy(
session,
resource_uri: str,
resource_type: str,
old_group: str,
new_group: str,
new_permissions: [str]
) -> models.ResourcePolicy:
ResourcePolicy.delete_resource_policy(
session=session,
group=old_group,
resource_uri=resource_uri,
resource_type=resource_type,
)
return ResourcePolicy.attach_resource_policy(
session=session,
group=new_group,
resource_uri=resource_uri,
permissions=new_permissions,
resource_type=resource_type,
)

@staticmethod
def attach_resource_policy(
session,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,53 +12,17 @@ import {
import { Formik } from 'formik';
import { useSnackbar } from 'notistack';
import PropTypes from 'prop-types';
import React, { useEffect, useState } from 'react';
import React from 'react';
import * as Yup from 'yup';
import { Defaults } from 'design';
import { SET_ERROR, useDispatch } from 'globalErrors';
import { listEnvironmentGroups, useClient } from 'services';
import { useClient, useFetchGroups } from 'services';
import { addConsumptionRoleToEnvironment } from '../services';

export const EnvironmentRoleAddForm = (props) => {
const { environment, onClose, open, reloadRoles, ...other } = props;
const { enqueueSnackbar } = useSnackbar();
const dispatch = useDispatch();
const client = useClient();
const [loadingGroups, setLoadingGroups] = useState(true);
const [groupOptions, setGroupOptions] = useState([]);

const fetchGroups = async (environmentUri) => {
try {
setLoadingGroups(true);
const response = await client.query(
listEnvironmentGroups({
filter: Defaults.selectListFilter,
environmentUri
})
);
if (!response.errors) {
setGroupOptions(
response.data.listEnvironmentGroups.nodes.map((g) => ({
value: g.groupUri,
label: g.groupUri
}))
);
} else {
dispatch({ type: SET_ERROR, error: response.errors[0].message });
}
} catch (e) {
dispatch({ type: SET_ERROR, error: e.message });
} finally {
setLoadingGroups(false);
}
};

useEffect(() => {
if (client && environment) {
fetchGroups(environment.environmentUri).catch((e) =>
dispatch({ type: SET_ERROR, error: e.message })
);
}
}, [client, environment, dispatch]);

async function submit(values, setStatus, setSubmitting, setErrors) {
try {
Expand Down Expand Up @@ -98,6 +62,8 @@ export const EnvironmentRoleAddForm = (props) => {
}
}

let { groupOptions, loadingGroups } = useFetchGroups(environment);

if (!environment) {
return null;
}
Expand Down
Loading

0 comments on commit d86c07f

Please sign in to comment.