Skip to content
Snippets Groups Projects
Commit d685a160 authored by Yas Naoi's avatar Yas Naoi Committed by Yas Naoi
Browse files

Issue #3056198 by baldwinlouie, yas, Xiaohua Guan: Add ability to switch to...

Issue #3056198 by baldwinlouie, yas, Xiaohua Guan: Add ability to switch to another roles after assuming a role
parent 96bb5c6e
No related branches found
No related tags found
No related merge requests found
Showing
with 375 additions and 66 deletions
......@@ -739,6 +739,21 @@ function aws_cloud_update_8144() {
cloud_update_yml_definitions(['views.view.aws_instances.yml'], 'aws_cloud');
}
/**
* Add the Switch Role fields.
*/
function aws_cloud_update_8145() {
aws_cloud_add_fields(
'cloud_config',
'aws_ec2',
[
'field_switch_role',
'field_switch_role_account_id',
'field_switch_role_iam_role',
]
);
}
/**
* Helper function to add fields to the entity type.
*
......
......@@ -632,6 +632,11 @@ function aws_cloud_update_ec2_resources(
}
else {
$account_id = $cloud_config->get('field_account_id')->value;
$assume_role = $cloud_config->get('field_assume_role')->value;
$switch_role = $cloud_config->get('field_switch_role')->value;
if (isset($assume_role) && isset($switch_role) && $switch_role == TRUE && $assume_role == TRUE) {
$account_id = trim($cloud_config->get('field_switch_role_account_id')->value);
}
$aws_ec2_service->updateImages(['Owners' => [$account_id]], TRUE);
}
}
......@@ -1874,6 +1879,8 @@ function aws_cloud_form_cloud_config_aws_ec2_add_form_validate(array &$form, For
function aws_cloud_form_cloud_config_aws_ec2_credentials_validate(array &$form, FormStateInterface $form_state) {
$use_credentials = $form_state->getValue('field_use_instance_credentials');
$assume_role = $form_state->getValue('field_assume_role');
$switch_role = $form_state->getValue('field_switch_role');
$iam_role = $form_state->getValue('field_iam_role');
if ($use_credentials['value'] == FALSE) {
$access_key = $form_state->getValue('field_access_key');
......@@ -1894,7 +1901,6 @@ function aws_cloud_form_cloud_config_aws_ec2_credentials_validate(array &$form,
}
if ($assume_role['value'] == TRUE) {
$iam_role = $form_state->getValue('field_iam_role');
if (empty($iam_role[0]['value'])) {
$form_state->setErrorByName(
'field_iam_role',
......@@ -1902,6 +1908,35 @@ function aws_cloud_form_cloud_config_aws_ec2_credentials_validate(array &$form,
);
}
}
if ($switch_role['value'] == TRUE) {
if ($assume_role['value'] == FALSE) {
$form_state->setErrorByName('field_assume_role', t('Assume Role must be enabled.'));
}
if (empty($iam_role[0]['value'])) {
$form_state->setErrorByName(
'field_iam_role',
t('IAM role name required.')
);
}
$switch_role_account_id = $form_state->getValue('field_switch_role_account_id');
$switch_role_iam_role = $form_state->getValue('field_switch_role_iam_role');
if (empty($switch_role_account_id[0]['value'])) {
$form_state->setErrorByName(
'field_switch_role_account_id',
t('Switch role account id required.')
);
}
if (empty($switch_role_iam_role[0]['value'])) {
$form_state->setErrorByName(
'field_switch_role_iam_role',
t('Switch role IAM role required.')
);
}
}
}
/**
......@@ -2064,6 +2099,18 @@ function aws_cloud_form_cloud_config_aws_ec2_form_common_alter(&$form, FormState
'field_assume_role',
'field_iam_role',
],
'subfieldsets' => [
[
'name' => 'switch_role',
'title' => t('Switch Role'),
'open' => TRUE,
'fields' => [
'field_switch_role',
'field_switch_role_account_id',
'field_switch_role_iam_role',
],
],
],
],
],
],
......@@ -2142,7 +2189,7 @@ function aws_cloud_form_reorder(array &$form, array $fieldset_defs) {
unset($form[$field_name]);
}
// Support an extra fieldset.
// Support second level fieldset.
if (isset($fieldset_def['subfieldsets'])) {
foreach ($fieldset_def['subfieldsets'] as $subfieldset_def) {
$subfieldset_name = $subfieldset_def['name'];
......@@ -2160,6 +2207,27 @@ function aws_cloud_form_reorder(array &$form, array $fieldset_defs) {
$form[$fieldset_name][$subfieldset_name][$subfield]['#weight'] = $weight++;
unset($form[$subfield]);
}
// Third level field set.
if (isset($subfieldset_def['subfieldsets'])) {
foreach ($subfieldset_def['subfieldsets'] as $third_fieldset_def) {
$third_fieldset_name = $third_fieldset_def['name'];
$form[$fieldset_name][$subfieldset_name][$third_fieldset_name] = [
'#type' => 'details',
'#title' => $third_fieldset_def['title'],
'#weight' => $weight++,
'#open' => $third_fieldset_def['open'],
];
foreach ($third_fieldset_def['fields'] as $third_field) {
if (!isset($form[$third_field])) {
continue;
}
$form[$fieldset_name][$subfieldset_name][$third_fieldset_name][$third_field] = $form[$third_field];
$form[$fieldset_name][$subfieldset_name][$third_fieldset_name][$third_field]['#weight'] = $weight++;
unset($form[$third_field]);
}
}
}
}
}
}
......
......@@ -4,6 +4,7 @@ dependencies:
config:
- cloud.cloud_config_type.aws_ec2
- field.field.cloud_config.aws_ec2.field_access_key
- field.field.cloud_config.aws_ec2.field_account_id
- field.field.cloud_config.aws_ec2.field_api_endpoint_uri
- field.field.cloud_config.aws_ec2.field_api_version
- field.field.cloud_config.aws_ec2.field_assume_role
......@@ -13,10 +14,12 @@ dependencies:
- field.field.cloud_config.aws_ec2.field_image_upload_url
- field.field.cloud_config.aws_ec2.field_region
- field.field.cloud_config.aws_ec2.field_secret_key
- field.field.cloud_config.aws_ec2.field_account_id
- field.field.cloud_config.aws_ec2.field_spreadsheet_pricing_url
- field.field.cloud_config.aws_ec2.field_switch_role
- field.field.cloud_config.aws_ec2.field_switch_role_account_id
- field.field.cloud_config.aws_ec2.field_switch_role_iam_role
- field.field.cloud_config.aws_ec2.field_use_instance_credentials
- field.field.cloud_config.aws_ec2.field_x_509_certificate
- field.field.cloud_config.aws_ec2.field_spreadsheet_pricing_url
id: cloud_config.aws_ec2.default
targetEntityType: cloud_config
bundle: aws_ec2
......@@ -30,6 +33,14 @@ content:
third_party_settings: { }
type: string_textfield
region: content
field_account_id:
weight: 10
settings:
size: 60
placeholder: ''
third_party_settings: { }
type: string_textfield
region: content
field_api_endpoint_uri:
weight: 6
settings: { }
......@@ -93,21 +104,36 @@ content:
third_party_settings: { }
type: string_textfield
region: content
field_use_instance_credentials:
weight: 103
field_switch_role:
weight: 104
settings:
display_label: true
third_party_settings: { }
type: boolean_checkbox
region: content
field_account_id:
weight: 10
field_switch_role_account_id:
weight: 105
settings:
size: 60
placeholder: ''
third_party_settings: { }
type: string_textfield
region: content
field_switch_role_iam_role:
weight: 106
settings:
size: 60
placeholder: ''
third_party_settings: { }
type: string_textfield
region: content
field_use_instance_credentials:
weight: 103
settings:
display_label: true
third_party_settings: { }
type: boolean_checkbox
region: content
field_x_509_certificate:
weight: 12
settings:
......
......@@ -4,6 +4,7 @@ dependencies:
config:
- cloud.cloud_config_type.aws_ec2
- field.field.cloud_config.aws_ec2.field_access_key
- field.field.cloud_config.aws_ec2.field_account_id
- field.field.cloud_config.aws_ec2.field_api_endpoint_uri
- field.field.cloud_config.aws_ec2.field_api_version
- field.field.cloud_config.aws_ec2.field_assume_role
......@@ -13,10 +14,12 @@ dependencies:
- field.field.cloud_config.aws_ec2.field_image_upload_url
- field.field.cloud_config.aws_ec2.field_region
- field.field.cloud_config.aws_ec2.field_secret_key
- field.field.cloud_config.aws_ec2.field_account_id
- field.field.cloud_config.aws_ec2.field_spreadsheet_pricing_url
- field.field.cloud_config.aws_ec2.field_switch_role
- field.field.cloud_config.aws_ec2.field_switch_role_account_id
- field.field.cloud_config.aws_ec2.field_switch_role_iam_role
- field.field.cloud_config.aws_ec2.field_use_instance_credentials
- field.field.cloud_config.aws_ec2.field_x_509_certificate
- field.field.cloud_config.aws_ec2.field_spreadsheet_pricing_url
module:
- options
- user
......@@ -33,6 +36,14 @@ content:
third_party_settings: { }
type: string
region: content
field_account_id:
weight: 8
label: above
settings:
link_to_entity: false
third_party_settings: { }
type: string
region: content
field_api_endpoint_uri:
weight: 4
label: above
......@@ -102,8 +113,16 @@ content:
third_party_settings: { }
type: string
region: content
field_use_instance_credentials:
weight: 13
field_spreadsheet_pricing_url:
weight: 100
label: above
settings:
link_to_entity: false
third_party_settings: { }
type: string
region: content
field_switch_role:
weight: 101
label: above
settings:
format: default
......@@ -112,28 +131,38 @@ content:
third_party_settings: { }
type: boolean
region: content
field_account_id:
weight: 8
field_switch_role_account_id:
weight: 102
label: above
settings:
link_to_entity: false
third_party_settings: { }
type: string
region: content
field_x_509_certificate:
weight: 10
field_switch_role_iam_role:
weight: 103
label: above
settings: { }
settings:
link_to_entity: false
third_party_settings: { }
type: basic_string
type: string
region: content
field_spreadsheet_pricing_url:
weight: 100
field_use_instance_credentials:
weight: 13
label: above
settings:
link_to_entity: false
format: default
format_custom_false: ''
format_custom_true: ''
third_party_settings: { }
type: string
type: boolean
region: content
field_x_509_certificate:
weight: 10
label: above
settings: { }
third_party_settings: { }
type: basic_string
region: content
name:
label: above
......
langcode: en
status: true
dependencies:
config:
- cloud.cloud_config_type.aws_ec2
- field.storage.cloud_config.field_switch_role
id: cloud_config.aws_ec2.field_switch_role
field_name: field_switch_role
entity_type: cloud_config
bundle: aws_ec2
label: 'Switch Role'
description: 'Switch to another IAM roles after assuming role.'
required: false
translatable: false
default_value:
-
value: 0
default_value_callback: ''
settings:
on_label: 'On'
off_label: 'Off'
field_type: boolean
langcode: en
status: true
dependencies:
config:
- cloud.cloud_config_type.aws_ec2
- field.storage.cloud_config.field_switch_role_account_id
id: cloud_config.aws_ec2.field_switch_role_account_id
field_name: field_switch_role_account_id
entity_type: cloud_config
bundle: aws_ec2
label: 'Switch Role Account ID'
description: 'Account ID for switching IAM role.'
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings: { }
field_type: string
langcode: en
status: true
dependencies:
config:
- cloud.cloud_config_type.aws_ec2
- field.storage.cloud_config.field_switch_role_iam_role
id: cloud_config.aws_ec2.field_switch_role_iam_role
field_name: field_switch_role_iam_role
entity_type: cloud_config
bundle: aws_ec2
label: 'Switch Role IAM Role'
description: 'IAM role name for switching.'
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings: { }
field_type: string
langcode: en
status: true
dependencies:
module:
- cloud
id: cloud_config.field_switch_role
field_name: field_switch_role
entity_type: cloud_config
type: boolean
settings: { }
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
langcode: en
status: true
dependencies:
module:
- cloud
id: cloud_config.field_switch_role_account_id
field_name: field_switch_role_account_id
entity_type: cloud_config
type: string
settings:
max_length: 255
is_ascii: false
case_sensitive: false
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
langcode: en
status: true
dependencies:
module:
- cloud
id: cloud_config.field_switch_role_iam_role
field_name: field_switch_role_iam_role
entity_type: cloud_config
type: string
settings:
max_length: 255
is_ascii: false
case_sensitive: false
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
......@@ -7,12 +7,10 @@
if($(element).is(':checked')) {
$('#edit-field-access-key-wrapper').hide();
$('#edit-field-secret-key-wrapper').hide();
$('#edit-assume-role').hide();
}
else {
$('#edit-field-access-key-wrapper').show();
$('#edit-field-secret-key-wrapper').show();
$('#edit-assume-role').show();
}
}
};
......
......@@ -137,6 +137,12 @@ class ApiController extends ControllerBase implements ApiControllerInterface {
if (!empty($cloud_config_entities)) {
$cloud_config = reset($cloud_config_entities);
$account_id = $cloud_config->get('field_account_id')->value;
// Use the switch role account_id if switching is enabled.
$assume_role = $cloud_config->get('field_assume_role')->value;
$switch_role = $cloud_config->get('field_switch_role')->value;
if (isset($assume_role) && isset($switch_role) && $switch_role == TRUE && $assume_role == TRUE) {
$account_id = trim($cloud_config->get('field_switch_role_account_id')->value);
}
}
if ($account_id) {
......
......@@ -106,6 +106,13 @@ class AwsCloudConfigPlugin extends PluginBase implements CloudConfigPluginInterf
if (isset($assume_role) && $assume_role == TRUE) {
$credentials['assume_role'] = TRUE;
$credentials['role_arn'] = sprintf("arn:aws:iam::%s:role/%s", trim($entity->get('field_account_id')->value), trim($entity->get('field_iam_role')->value));
// Setup switch role configurations.
$switch_role = $entity->get('field_switch_role')->value;
if (isset($switch_role) && $switch_role == TRUE) {
$credentials['switch_role'] = TRUE;
$credentials['switch_role_arn'] = sprintf("arn:aws:iam::%s:role/%s", trim($entity->get('field_switch_role_account_id')->value), trim($entity->get('field_switch_role_iam_role')->value));
}
}
if (isset($use_instance_credentials) && $use_instance_credentials == TRUE) {
......
......@@ -179,35 +179,55 @@ class AwsEc2Service implements AwsEc2ServiceInterface {
'region' => $credentials['region'],
'version' => $credentials['version'],
];
$provider = FALSE;
// Load credentials if needed.
if ($credentials['use_instance_credentials'] == FALSE) {
// Assume role using credential ini file.
$provider = CredentialProvider::ini('default', $credentials['ini_file']);
$provider = CredentialProvider::memoize($provider);
}
if ($credentials['assume_role'] == TRUE) {
if ($credentials['assume_role'] == TRUE) {
$sts_params = [
'region' => $credentials['region'],
'version' => $credentials['version'],
];
if ($provider != FALSE) {
$sts_params['credentials'] = $provider;
}
$assumeRoleCredentials = new AssumeRoleCredentialProvider([
'client' => new StsClient($sts_params),
'assume_role_params' => [
'RoleArn' => $credentials['role_arn'],
'RoleSessionName' => 'ec2_client_assume_role',
],
]);
// Memoize takes care of re-authenticating when the tokens expire.
$assumeRoleCredentials = CredentialProvider::memoize($assumeRoleCredentials);
$ec2_params['credentials'] = $assumeRoleCredentials;
$sts_params = [
// If switch role is enabled, execute one more assume role.
if ($credentials['switch_role'] == TRUE) {
$switch_sts_params = [
'region' => $credentials['region'],
'version' => $credentials['version'],
'credentials' => $provider,
'credentials' => $assumeRoleCredentials,
];
$assumeRoleCredentials = new AssumeRoleCredentialProvider([
'client' => new StsClient($sts_params),
$switchRoleCredentials = new AssumeRoleCredentialProvider([
'client' => new StsClient($switch_sts_params),
'assume_role_params' => [
'RoleArn' => $credentials['role_arn'],
'RoleSessionName' => 'ec2_client_assume_role',
'RoleArn' => $credentials['switch_role_arn'],
'RoleSessionName' => 'ec2_client_switch_role',
],
]);
// Memoize takes care of re-authenticating when the tokens expire.
$assumeRoleCredentials = CredentialProvider::memoize($assumeRoleCredentials);
$ec2_params['credentials'] = $assumeRoleCredentials;
}
else {
$ec2_params['credentials'] = $provider;
$switchRoleCredentials = CredentialProvider::memoize($switchRoleCredentials);
$ec2_params['credentials'] = $switchRoleCredentials;
}
}
elseif ($provider != FALSE) {
$ec2_params['credentials'] = $provider;
}
$ec2_client = new Ec2Client($ec2_params);
}
catch (\Exception $e) {
......@@ -348,7 +368,7 @@ class AwsEc2Service implements AwsEc2ServiceInterface {
$this->messenger->addError($this->t('Message: @msg', ['@msg' => $e->getAwsErrorMessage()]));
}
catch (\InvalidArgumentException $e) {
catch (\Exception $e) {
$this->messenger->addError($e->getMessage());
}
return $results;
......@@ -575,7 +595,14 @@ class AwsEc2Service implements AwsEc2ServiceInterface {
*/
public function describeSnapshots(array $params = []) {
$params += $this->getDefaultParameters();
$params['RestorableByUserIds'] = [$this->cloudConfigPluginManager->loadConfigEntity()->get('field_account_id')->value];
$cloud_config = $this->cloudConfigPluginManager->loadConfigEntity();
$account_id = $cloud_config->get('field_account_id')->value;
$assume_role = $cloud_config->get('field_assume_role')->value;
$switch_role = $cloud_config->get('field_switch_role')->value;
if (isset($assume_role) && isset($switch_role) && $switch_role == TRUE && $assume_role == TRUE) {
$account_id = trim($cloud_config->get('field_switch_role_account_id')->value);
}
$params['RestorableByUserIds'] = [$account_id];
$results = $this->execute('DescribeSnapshots', $params);
return $results;
}
......@@ -1044,9 +1071,6 @@ class AwsEc2Service implements AwsEc2ServiceInterface {
foreach ($image_entities as $image) {
$stale[$image->getImageId()] = $image;
}
/* @var \Drupal\Core\Batch\BatchBuilder $batch_builder */
$batch_builder = $this->initBatch('Image Update');
foreach ($result['Images'] as $image) {
// Keep track of images that do not exist anymore
// delete them after saving the rest of the images.
......
......@@ -187,7 +187,7 @@ class AwsIamService implements AwsIamServiceInterface {
$this->messenger->addError($this->t('Message: @msg', ['@msg' => $e->getAwsErrorMessage()]));
}
catch (\InvalidArgumentException $e) {
catch (\Exception $e) {
$this->messenger->addError($e->getMessage());
}
return $results;
......@@ -207,39 +207,60 @@ class AwsIamService implements AwsIamServiceInterface {
'region' => $credentials['region'],
'version' => $credentials['version'],
];
$provider = FALSE;
// Load credentials if needed.
if ($credentials['use_instance_credentials'] == FALSE) {
$provider = CredentialProvider::ini('default', $credentials['ini_file']);
$provider = CredentialProvider::memoize($provider);
}
if ($credentials['assume_role'] == TRUE) {
// Assume role.
$sts_params = [
if ($credentials['assume_role'] == TRUE) {
// Assume role.
$sts_params = [
'region' => $credentials['region'],
'version' => $credentials['version'],
];
if ($provider != FALSE) {
$sts_params['credentials'] = $provider;
}
$assumeRoleCredentials = new AssumeRoleCredentialProvider([
'client' => new StsClient($sts_params),
'assume_role_params' => [
'RoleArn' => $credentials['role_arn'],
'RoleSessionName' => 'iam_client_assume_role',
],
]);
// Memoize takes care of re-authenticating when the tokens expire.
$assumeRoleCredentials = CredentialProvider::memoize($assumeRoleCredentials);
$iam_params = [
'region' => $credentials['region'],
'version' => $credentials['version'],
'credentials' => $assumeRoleCredentials,
];
// If switch role is enabled, execute one more assume role.
if ($credentials['switch_role'] == TRUE) {
$switch_sts_params = [
'region' => $credentials['region'],
'version' => $credentials['version'],
'credentials' => $provider,
'credentials' => $assumeRoleCredentials,
];
$assumeRoleCredentials = new AssumeRoleCredentialProvider([
'client' => new StsClient($sts_params),
$switchRoleCredentials = new AssumeRoleCredentialProvider([
'client' => new StsClient($switch_sts_params),
'assume_role_params' => [
'RoleArn' => $credentials['role_arn'],
'RoleSessionName' => 'iam_client_assume_role',
'RoleArn' => $credentials['switch_role_arn'],
'RoleSessionName' => 'iam_client_switch_role',
],
]);
// Memoize takes care of re-authenticating when the tokens expire.
$assumeRoleCredentials = CredentialProvider::memoize($assumeRoleCredentials);
$iam_params = [
'region' => $credentials['region'],
'version' => $credentials['version'],
'credentials' => $assumeRoleCredentials,
];
}
else {
$iam_params['credentials'] = $provider;
$switchRoleCredentials = CredentialProvider::memoize($switchRoleCredentials);
$iam_params['credentials'] = $switchRoleCredentials;
}
}
elseif ($provider != FALSE) {
$iam_params['credentials'] = $provider;
}
$iam_client = new IamClient($iam_params);
}
catch (\Exception $e) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment