From 78d1e09a0de3ba2bc50ba7034457d7caa863a785 Mon Sep 17 00:00:00 2001 From: Dharini Jeeva Date: Mon, 18 Sep 2023 14:23:30 -0700 Subject: [PATCH] Icu 11022 update dynamic credentials in sb form (#1901) --- .../addon/generated/models/storage-bucket.js | 7 --- addons/api/addon/models/storage-bucket.js | 2 +- .../api/addon/serializers/storage-bucket.js | 51 ++++++++++++--- addons/api/mirage/config.js | 4 +- .../unit/serializers/storage-bucket-test.js | 62 ++++++++++++++++--- .../components/form/storage-bucket/index.hbs | 2 +- .../components/form/storage-bucket/index.js | 13 ++++ .../scope/storage-buckets/storage-bucket.js | 4 +- 8 files changed, 112 insertions(+), 33 deletions(-) diff --git a/addons/api/addon/generated/models/storage-bucket.js b/addons/api/addon/generated/models/storage-bucket.js index 53492bd38..335f2bffe 100644 --- a/addons/api/addon/generated/models/storage-bucket.js +++ b/addons/api/addon/generated/models/storage-bucket.js @@ -73,12 +73,6 @@ export default class GeneratedStorageBucketModel extends BaseModel { }) region; - @attr('string', { - readOnly: true, - isNestedAttribute: true, - }) - secrets_hmac; - @attr('boolean', { isNestedAttribute: true, description: 'If set to `true`, credential rotation is not performed.', @@ -120,7 +114,6 @@ export default class GeneratedStorageBucketModel extends BaseModel { @attr('object-as-array', { isNestedAttribute: true, description: 'The role tags to use.', - useLabels: true, }) role_tags; } diff --git a/addons/api/addon/models/storage-bucket.js b/addons/api/addon/models/storage-bucket.js index 7a15bc5c7..ee98d055a 100644 --- a/addons/api/addon/models/storage-bucket.js +++ b/addons/api/addon/models/storage-bucket.js @@ -36,7 +36,7 @@ export default class StorageBucketModel extends GeneratedStorageBucketModel { * @type {string} */ get credentialType() { - if (this.role_arn) { + if (this.role_arn && !this.access_key_id) { return TYPE_CREDENTIAL_DYNAMIC; } else { return TYPE_CREDENTIAL_STATIC; diff --git a/addons/api/addon/serializers/storage-bucket.js b/addons/api/addon/serializers/storage-bucket.js index 0be34a2a5..cb3941094 100644 --- a/addons/api/addon/serializers/storage-bucket.js +++ b/addons/api/addon/serializers/storage-bucket.js @@ -4,29 +4,62 @@ */ import ApplicationSerializer from './application'; +import { TYPE_CREDENTIAL_DYNAMIC } from '../models/storage-bucket'; +const fieldsByCredentialType = { + static: [ + 'access_key_id', + 'secret_access_key', + 'region', + 'disable_credential_rotation', + ], + dynamic: [ + 'role_arn', + 'role_external_id', + 'role_session_name', + 'role_tags', + 'disable_credential_rotation', + 'region', + ], +}; export default class StorageBucketSerializer extends ApplicationSerializer { serialize(snapshot) { const serialized = super.serialize(...arguments); - //Dynamic credentials do not allow credential rotation, and the API requires this field to be - //sent along with the dynamic credential fields - if (serialized.attributes.role_arn) { - serialized.attributes.disable_credential_rotation = true; - } + const { credentialType } = snapshot.record; if (!snapshot.record.isNew) { delete serialized.bucket_name; delete serialized.bucket_prefix; } + + if (credentialType === TYPE_CREDENTIAL_DYNAMIC) { + serialized.attributes.disable_credential_rotation = true; + } return serialized; } + serializeAttribute(snapshot, json, key, attribute) { + const value = super.serializeAttribute(...arguments); + const { credentialType } = snapshot.record; + const { options } = attribute; + // This deletes any fields that don't belong to the record's credential type + if (options.isNestedAttribute && json.attributes) { + // The key must be included in the fieldsByType list above + if (!fieldsByCredentialType[credentialType].includes(key)) + //API requires these fields to be null + json.attributes[key] = null; + } + + return value; + } + normalize(typeClass, hash, ...rest) { const normalizedHash = structuredClone(hash); - const normalized = super.normalize(typeClass, normalizedHash, ...rest); // Remove secret fields so we don't track them after creating/updating - normalized.data.attributes.access_key_id = null; - normalized.data.attributes.secret_access_key = null; - return normalized; + if (normalizedHash?.secrets?.access_key_id) { + delete normalizedHash.secrets.access_key_id; + delete normalizedHash.secrets.secret_access_key; + } + return super.normalize(typeClass, normalizedHash, ...rest); } } diff --git a/addons/api/mirage/config.js b/addons/api/mirage/config.js index 93bb8b15b..b7d29d2b8 100644 --- a/addons/api/mirage/config.js +++ b/addons/api/mirage/config.js @@ -696,10 +696,8 @@ function routes() { name: plugin_name, }; } - - // Remove the secrets and add the hmac in the response + // Remove the secrets delete attrs.secrets; - attrs.secrets_hmac = faker.git.commitSha(); return storageBuckets.create(attrs); } diff --git a/addons/api/tests/unit/serializers/storage-bucket-test.js b/addons/api/tests/unit/serializers/storage-bucket-test.js index 8bae81190..e9f3c3cdb 100644 --- a/addons/api/tests/unit/serializers/storage-bucket-test.js +++ b/addons/api/tests/unit/serializers/storage-bucket-test.js @@ -35,7 +35,6 @@ module('Unit | Serializer | storage bucket', function (hooks) { region: 'eu-west-1', access_key_id: 'foobars', secret_access_key: 'testing', - secrets_hmac: 'hmac', disable_credential_rotation: true, role_arn: null, role_external_id: null, @@ -78,7 +77,6 @@ module('Unit | Serializer | storage bucket', function (hooks) { region: 'eu-west-1', access_key_id: '', secret_access_key: '', - secrets_hmac: 'hmac', disable_credential_rotation: true, role_arn: 'arn', role_external_id: 'Example987', @@ -106,7 +104,7 @@ module('Unit | Serializer | storage bucket', function (hooks) { }; assert.deepEqual(record.serialize(), expectedResult); }); - test('it serializes when updating correctly', async function (assert) { + test('it serializes when updating a storage bucket with static credential correctly', async function (assert) { assert.expect(1); const store = this.owner.lookup('service:store'); const serializer = store.serializerFor('storage-bucket'); @@ -125,13 +123,8 @@ module('Unit | Serializer | storage bucket', function (hooks) { region: 'eu-west-1', access_key_id: 'foobars', secret_access_key: 'testing', - secrets_hmac: 'hmac', disable_credential_rotation: true, version: 1, - role_arn: null, - role_external_id: null, - role_session_name: null, - role_tags: [], }, }, }); @@ -161,6 +154,57 @@ module('Unit | Serializer | storage bucket', function (hooks) { assert.deepEqual(serializedRecord, expectedResult); }); + test('it serializes when updating a storage bucket with dynamic credential correctly', async function (assert) { + assert.expect(1); + const store = this.owner.lookup('service:store'); + const serializer = store.serializerFor('storage-bucket'); + store.push({ + data: { + id: '1', + type: 'storage-bucket', + attributes: { + type: TYPE_STORAGE_BUCKET_PLUGIN, + compositeType: TYPE_STORAGE_BUCKET_PLUGIN_AWS_S3, + name: 'AWS', + description: 'this has an aws plugin', + bucket_name: 'bucketname', + bucket_prefix: 'bucketprefix', + worker_filter: 'workerfilter', + region: 'eu-west-1', + disable_credential_rotation: true, + version: 1, + role_arn: 'arn', + role_external_id: 'Example987', + role_session_name: 'my-session', + role_tags: [ + { key: 'Project', value: 'Automation' }, + { key: 'foo', value: 'bar' }, + ], + }, + }, + }); + const record = store.peekRecord('storage-bucket', '1'); + const snapshot = record._createSnapshot(); + const serializedRecord = serializer.serialize(snapshot); + + const expectedResult = { + name: 'AWS', + description: 'this has an aws plugin', + type: TYPE_STORAGE_BUCKET_PLUGIN, + worker_filter: 'workerfilter', + attributes: { + region: 'eu-west-1', + disable_credential_rotation: true, + role_arn: 'arn', + role_external_id: 'Example987', + role_session_name: 'my-session', + role_tags: { Project: 'Automation', foo: 'bar' }, + }, + version: 1, + }; + assert.deepEqual(serializedRecord, expectedResult); + }); + test('it normalizes correctly', function (assert) { assert.expect(1); const store = this.owner.lookup('service:store'); @@ -179,7 +223,6 @@ module('Unit | Serializer | storage bucket', function (hooks) { region: 'eu-west-1', disable_credential_rotation: true, }, - secrets_hmac: 'this is secret', }; const normalized = serializer.normalizeSingleResponse( store, @@ -200,7 +243,6 @@ module('Unit | Serializer | storage bucket', function (hooks) { bucket_name: 'bucketname', bucket_prefix: 'bucketprefix', worker_filter: 'workerfilter', - secrets_hmac: 'this is secret', region: 'eu-west-1', disable_credential_rotation: true, access_key_id: null, diff --git a/ui/admin/app/components/form/storage-bucket/index.hbs b/ui/admin/app/components/form/storage-bucket/index.hbs index 5204230a0..71fe2b064 100644 --- a/ui/admin/app/components/form/storage-bucket/index.hbs +++ b/ui/admin/app/components/form/storage-bucket/index.hbs @@ -5,7 +5,7 @@