From 57481d2d15fad71bbfae84ba5c653e7cec23f693 Mon Sep 17 00:00:00 2001 From: Michael Shimkus Date: Wed, 31 Aug 2022 20:11:57 +0000 Subject: [PATCH 1/7] 3157 - Support server side encryption for S3 buckets --- .gitlab-ci.yml | 118 ++++++++++++++---- deployment-tool | 2 +- docs/userguide/aws-same-az.rst | 3 + docs/userguide/aws.rst | 3 + docs/userguide/example-declarations.rst | 29 +++++ ...aws-s3-server-side-encryption-aws-key.json | 39 ++++++ ...-s3-server-side-encryption-custom-key.json | 40 ++++++ package-lock.json | 117 +++++++++-------- package.json | 5 +- specs/openapi.yaml | 6 +- src/nodejs/failover.js | 2 + src/nodejs/providers/abstract/cloud.js | 2 + src/nodejs/providers/aws/cloud.js | 8 ++ src/nodejs/schema/base_schema.json | 36 +++++- .../functional/tests/providers/azure/tests.js | 4 +- test/unit/providers/awsProviderTests.js | 98 ++++++++++++++- 16 files changed, 430 insertions(+), 82 deletions(-) create mode 100644 examples/declarations/aws-s3-server-side-encryption-aws-key.json create mode 100644 examples/declarations/aws-s3-server-side-encryption-custom-key.json diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f73bbd3b..b86daaf5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,8 +2,8 @@ image: ${ARTIFACTORY_SERVER}/dockerhub-remote/node:8 stages: - check_content - - build_package - test + - build_package - test_functional_init - test_functional_execute - test_functional_cleanup @@ -68,28 +68,6 @@ check_content: tags: - cm-official-docker-executor -build_package: - image: ${ARTIFACTORY_SERVER}/dockerhub-remote/f5devcentral/containthedocs:rpmbuild - stage: build_package - except: - variables: - - $CI_COMMIT_REF_NAME == "docs_production" - - $CI_COMMIT_REF_NAME == "docs_staging" - script: - - echo 'CI BUILD' - # install packages: jq - - apt-get update - - apt-get install -y jq - # build RPM, handles dependency installation, etc. - - bash ./scripts/build_rpm.sh - tags: - - cm-official-docker-executor - artifacts: - name: f5-cloud-failover-$CI_BUILD_REF - paths: - - dist - expire_in: 1 month - # test package test_package: stage: test @@ -145,6 +123,28 @@ coverage: - coverage expire_in: 1 month +build_package: + image: ${ARTIFACTORY_SERVER}/dockerhub-remote/f5devcentral/containthedocs:rpmbuild + stage: build_package + except: + variables: + - $CI_COMMIT_REF_NAME == "docs_production" + - $CI_COMMIT_REF_NAME == "docs_staging" + script: + - echo 'CI BUILD' + # install packages: jq + - apt-get update + - apt-get install -y jq + # build RPM, handles dependency installation, etc. + - bash ./scripts/build_rpm.sh + tags: + - cm-official-docker-executor + artifacts: + name: f5-cloud-failover-$CI_BUILD_REF + paths: + - dist + expire_in: 1 month + ### Functional Tests Section # Functional Tests - Initialization phase (with 1 retries in a case of any failures) @@ -195,6 +195,8 @@ test_functional_init_azure: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "aws" + - $CF_ENV_CLOUD == "gcp" # init functional tests: azure - 1nic test_functional_init_azure_1nic: @@ -206,6 +208,8 @@ test_functional_init_azure_1nic: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "aws" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # init functional tests: aws - across network topology @@ -218,6 +222,8 @@ test_functional_init_aws_across_net: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" # init functional tests: aws - across network topology for 1nic test_functional_init_aws_across_net_1nic: @@ -230,6 +236,8 @@ test_functional_init_aws_across_net_1nic: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # init functional tests: aws - same network topology in us-west-2 @@ -242,6 +250,8 @@ test_functional_init_aws: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # init functional tests: aws - same network topology in us-east-1 @@ -252,6 +262,10 @@ test_functional_init_aws_east: CF_ENV_USE_AVAILABILITY_ZONES: "false" CF_ENV_REGION: "us-east-1" when: manual + except: + variables: + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" # init functional tests: aws - same network topology in ca-central-1 test_functional_init_aws_ca_central: @@ -261,6 +275,10 @@ test_functional_init_aws_ca_central: CF_ENV_USE_AVAILABILITY_ZONES: "false" CF_ENV_REGION: "ca-central-1" when: manual + except: + variables: + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" # init functional tests: aws - same network topology for 1nic test_functional_init_aws_1nic: @@ -273,6 +291,8 @@ test_functional_init_aws_1nic: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # init functional tests: gcp @@ -284,6 +304,8 @@ test_functional_init_gcp: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "aws" # init functional tests: gcp no forwarding test_functional_init_gcp_no_forwarding: @@ -295,6 +317,8 @@ test_functional_init_gcp_no_forwarding: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "aws" # Functional Tests - Execute phase (with no retries) .test_functional_execute_generic: &test_functional_execute_generic @@ -349,6 +373,8 @@ test_functional_execute_azure: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "aws" + - $CF_ENV_CLOUD == "gcp" # run functional tests: azure 1 nic test_functional_execute_azure_1nic: @@ -366,6 +392,8 @@ test_functional_execute_azure_1nic: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "aws" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # run functional tests: aws - across network topology @@ -384,6 +412,8 @@ test_functional_execute_aws_across_net: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" # run functional tests: aws - across network topology for 1nic test_functional_execute_aws_across_net_1nic: @@ -402,6 +432,8 @@ test_functional_execute_aws_across_net_1nic: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # run functional tests: aws - same network topology @@ -420,6 +452,8 @@ test_functional_execute_aws: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # run functional tests: aws - same network topology - us-east-1 @@ -436,6 +470,10 @@ test_functional_execute_aws_east: - test_functional_init_aws_east - build_package when: manual + except: + variables: + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" # run functional tests: aws - same network topology - ca-central-1 test_functional_execute_aws_ca_central: @@ -451,6 +489,10 @@ test_functional_execute_aws_ca_central: - test_functional_init_aws_ca_central - build_package when: manual + except: + variables: + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" # run functional tests: aws - same network topology for 1nic test_functional_execute_aws_1nic: @@ -469,6 +511,8 @@ test_functional_execute_aws_1nic: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # run functional tests: gcp with forwarding rule @@ -486,6 +530,8 @@ test_functional_execute_gcp: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "aws" # run functional tests: gcp without forwarding rules test_functional_execute_gcp_no_forwarding: @@ -502,6 +548,8 @@ test_functional_execute_gcp_no_forwarding: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "aws" # Functional Tests - Cleanup phase (executes always with 1 retry in a case of any failures) .test_functional_cleanup_generic: &test_functional_cleanup_generic @@ -554,6 +602,8 @@ test_functional_cleanup_azure: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "aws" + - $CF_ENV_CLOUD == "gcp" # run functional tests: azure_1nic test_functional_cleanup_azure_1nic: @@ -571,6 +621,8 @@ test_functional_cleanup_azure_1nic: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "aws" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # run functional tests: aws - across network topology @@ -589,6 +641,8 @@ test_functional_cleanup_aws_across_net: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" # run functional tests: aws - across network topology for 1nic test_functional_cleanup_aws_across_net_1nic: @@ -607,6 +661,8 @@ test_functional_cleanup_aws_across_net_1nic: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # run functional tests: aws - same network topology @@ -625,6 +681,8 @@ test_functional_cleanup_aws: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # run functional tests: aws - same network topology - us-east-1 @@ -641,6 +699,10 @@ test_functional_cleanup_aws_east: - test_functional_init_aws_east - test_functional_execute_aws_east when: manual + except: + variables: + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" # run functional tests: aws - same network topology - ca-central-1 test_functional_cleanup_aws_ca_central: @@ -656,6 +718,10 @@ test_functional_cleanup_aws_ca_central: - test_functional_init_aws_ca_central - test_functional_execute_aws_ca_central when: manual + except: + variables: + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" # run functional tests: aws - same network topology for 1nic test_functional_cleanup_aws_1nic: @@ -674,6 +740,8 @@ test_functional_cleanup_aws_1nic: except: variables: - $TESTS_TIER == "1" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "gcp" - $CI_COMMIT_MESSAGE =~ /smart:run_functional_tests/ # run functional tests: gcp @@ -691,6 +759,8 @@ test_functional_cleanup_gcp: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "aws" # run functional tests: gcp no forwarding rule test_functional_cleanup_gcp_no_forwarding: @@ -708,6 +778,8 @@ test_functional_cleanup_gcp_no_forwarding: except: variables: - $TESTS_TIER == "2" + - $CF_ENV_CLOUD == "azure" + - $CF_ENV_CLOUD == "aws" ### End of Functional Tests diff --git a/deployment-tool b/deployment-tool index fda6f259..2e673f24 160000 --- a/deployment-tool +++ b/deployment-tool @@ -1 +1 @@ -Subproject commit fda6f2596d5faba7a962cc0f21ae142f742519d6 +Subproject commit 2e673f24f60e150c572e8655644549c2216430ac diff --git a/docs/userguide/aws-same-az.rst b/docs/userguide/aws-same-az.rst index 15b8da22..c051c4fb 100644 --- a/docs/userguide/aws-same-az.rst +++ b/docs/userguide/aws-same-az.rst @@ -125,6 +125,9 @@ In order to successfully implement CFE in AWS, you need an AWS Identity and Acce s3:ListAllMyBuckets \* Current Account externalStorage To discover (using scopingTags) bucket used for failover state file. s3:ListBucket S3 Bucket ID Optional externalStorage To return information about a bucket. s3:PutObject S3 Bucket ID/Key Optional externalStorage To write failover state file. + kms:DescribeKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. + kms:GenerateDataKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. + kms:Decrypt KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. ======================================== ============================== ======================= ======================= ===================================================================================================================== | | diff --git a/docs/userguide/aws.rst b/docs/userguide/aws.rst index e090d194..7276fe96 100644 --- a/docs/userguide/aws.rst +++ b/docs/userguide/aws.rst @@ -121,6 +121,9 @@ In order to successfully implement CFE in AWS, you need an AWS Identity and Acce s3:ListAllMyBuckets \* Current Account externalStorage To discover (using scopingTags) bucket used for failover state file. s3:ListBucket S3 Bucket ID Optional externalStorage To return information about a bucket. s3:PutObject S3 Bucket ID/Key Optional externalStorage To write failover state file. + kms:DescribeKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. + kms:GenerateDataKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. + kms:Decrypt KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. ======================================== ============================== ======================= ======================= ===================================================================================================================== | diff --git a/docs/userguide/example-declarations.rst b/docs/userguide/example-declarations.rst index 982fab03..da6101c2 100644 --- a/docs/userguide/example-declarations.rst +++ b/docs/userguide/example-declarations.rst @@ -121,6 +121,35 @@ This example shows a BIG-IP cluster managing route tables in multiple subscripti :fonticon:`fa fa-download` :download:`azureRouteTablesInMutipleSubscriptions.json <../../examples/declarations/azureRouteTablesInMutipleSubscriptions.json>` +.. _aws-sse-aws-key: + +Example Declaration Using AWS S3 Server-side encryption - AWS managed key +------------------------------------------------------------------------- +This example shows how to configure CFE when the S3 bucket used for failover state uses server-side KMS encryption with the default AWS managed key. + +.. literalinclude:: ../../examples/declarations/aws-s3-server-side-encryption-aws-key.json + :language: json + :caption: AWS Server-side encryption with AWS managed key + :tab-width: 4 + :linenos: + +:fonticon:`fa fa-download` :download:`aws-s3-server-side-encryption-aws-key.json <../../examples/declarations/aws-s3-server-side-encryption-aws-key.json>` + +.. _aws-sse-custom-key: + +Example Declaration Using AWS S3 Server-side encryption - Custom key +-------------------------------------------------------------------- +This example shows how to configure CFE when the S3 bucket used for failover state uses server-side KMS encryption with a customer-provided key. + +AWS S3 Server-side encryption - Custom key + +.. literalinclude:: ../../examples/declarations/aws-s3-server-side-encryption-custom-key.json + :language: json + :caption: AWS Server-side encryption with custom key + :tab-width: 4 + :linenos: + +:fonticon:`fa fa-download` :download:`aws-s3-server-side-encryption-custom-key.json <../../examples/declarations/aws-s3-server-side-encryption-custom-key.json>` Example Declaration Setting the Log Level ----------------------------------------- diff --git a/examples/declarations/aws-s3-server-side-encryption-aws-key.json b/examples/declarations/aws-s3-server-side-encryption-aws-key.json new file mode 100644 index 00000000..21dea8bd --- /dev/null +++ b/examples/declarations/aws-s3-server-side-encryption-aws-key.json @@ -0,0 +1,39 @@ +{ + "class": "Cloud_Failover", + "environment": "aws", + "controls": { + "class": "Controls", + "logLevel": "silly" + }, + "externalStorage": { + "scopingTags": { + "f5_cloud_failover_label": "mydeployment" + }, + "encryption": { + "serverSide": { + "enabled": true, + "algorithm": "aws:kms" + } + } + }, + "failoverAddresses": { + "enabled": true, + "scopingTags": { + "f5_cloud_failover_label": "mydeployment" + } + }, + "failoverRoutes": { + "enabled": true, + "scopingTags": { + "f5_cloud_failover_label": "mydeployment" + }, + "scopingAddressRanges": [ + { + "range": "0.0.0.0/0", + "nextHopAddresses": { + "discoveryType": "routeTag" + } + } + ] + } +} diff --git a/examples/declarations/aws-s3-server-side-encryption-custom-key.json b/examples/declarations/aws-s3-server-side-encryption-custom-key.json new file mode 100644 index 00000000..cf9320d5 --- /dev/null +++ b/examples/declarations/aws-s3-server-side-encryption-custom-key.json @@ -0,0 +1,40 @@ +{ + "class": "Cloud_Failover", + "environment": "aws", + "controls": { + "class": "Controls", + "logLevel": "silly" + }, + "externalStorage": { + "scopingTags": { + "f5_cloud_failover_label": "mydeployment" + }, + "encryption": { + "serverSide": { + "enabled": true, + "algorithm": "aws:kms", + "keyId": "myCustomKmsKey" + } + } + }, + "failoverAddresses": { + "enabled": true, + "scopingTags": { + "f5_cloud_failover_label": "mydeployment" + } + }, + "failoverRoutes": { + "enabled": true, + "scopingTags": { + "f5_cloud_failover_label": "mydeployment" + }, + "scopingAddressRanges": [ + { + "range": "0.0.0.0/0", + "nextHopAddresses": { + "discoveryType": "routeTag" + } + } + ] + } +} diff --git a/package-lock.json b/package-lock.json index a567aee7..4229e5f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "f5-cloud-failover", - "version": "1.12.0", + "version": "1.13.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -99,7 +99,7 @@ "requires": { "@azure/ms-rest-azure-env": "^2.0.0", "@azure/ms-rest-js": "^2.0.4", - "adal-node": "^0.1.28" + "adal-node": "^0.2.2" }, "dependencies": { "@azure/ms-rest-js": { @@ -108,25 +108,48 @@ "integrity": "sha512-LLi4jRe/qy5IM8U2CkoDgSZp2OH+MgDe2wePmhz8uY84Svc53EhHaamVyoU6BjjHBxvCRh1vcD1urJDccrxqIw==", "dev": true, "requires": { - "@types/node-fetch": "^2.3.7", - "@types/tunnel": "0.0.1", + "@azure/core-auth": "^1.1.4", "abort-controller": "^3.0.0", "form-data": "^2.5.0", - "node-fetch": "^2.6.0", + "node-fetch": "^2.6.7", "tough-cookie": "^3.0.1", "tslib": "^1.10.0", "tunnel": "0.0.6", - "uuid": "^3.3.2", + "uuid": "^8.3.2", "xml2js": "^0.4.19" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "adal-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.3.tgz", - "integrity": "sha512-gMKr8RuYEYvsj7jyfCv/4BfKToQThz20SP71N3AtFn3ia3yAR8Qt2T3aVQhuJzunWs2b38ZsQV0qsZPdwZr7VQ==", + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.1.28.tgz", + "integrity": "sha512-98nQ5MQSyJR0ZY/R0Mue/cv4OkebRyKz4hS40GdkZU42Bq49ldHeup7UeAo/0vROMB57CX2et6IF0U/Pe1rY3A==", "dev": true, "requires": { - "@types/node": "*" + "@types/node": "^8.0.47", + "async": ">=0.6.0", + "date-utils": "*", + "jws": "3.x.x", + "request": ">= 2.52.0", + "underscore": ">= 1.3.1", + "uuid": "^3.1.0", + "xmldom": ">= 0.1.x", + "xpath.js": "~1.1.0" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "form-data": { @@ -140,6 +163,27 @@ "mime-types": "^2.1.12" } }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dev": true, + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "tough-cookie": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", @@ -160,8 +204,7 @@ "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" } } }, @@ -1153,29 +1196,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.63.tgz", "integrity": "sha512-g+nSkeHFDd2WOQChfmy9SAXLywT47WZBrGS/NC5ym5PJ8c8RC6l4pbGaUW/X0+eZJnXw6/AVNEouXWhV4iz72Q==" }, - "@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", - "dev": true, - "requires": { - "@types/node": "*", - "form-data": "^3.0.0" - }, - "dependencies": { - "form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - } - } - }, "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -2525,9 +2545,9 @@ }, "dependencies": { "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.1.0.tgz", + "integrity": "sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ==", "optional": true }, "make-dir": { @@ -2604,9 +2624,9 @@ }, "dependencies": { "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha512-5mO7DX4CbJzp9zjaFXusQQ4tzKJARjNB1Ih1pVBi8wkbmXy/xzIDgEMXxWePLzt2OdFwaxfneIlT1nCiXubrPQ==", "optional": true } } @@ -5253,14 +5273,6 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, - "json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "requires": { - "bignumber.js": "^9.0.0" - } - }, "json-edm-parser": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz", @@ -9544,6 +9556,13 @@ "eyes": "0.1.x", "isstream": "0.1.x", "stack-trace": "0.0.x" + }, + "dependencies": { + "async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha512-5mO7DX4CbJzp9zjaFXusQQ4tzKJARjNB1Ih1pVBi8wkbmXy/xzIDgEMXxWePLzt2OdFwaxfneIlT1nCiXubrPQ==" + } } }, "word-wrap": { diff --git a/package.json b/package.json index ee878d9a..37d56562 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "f5-cloud-failover", - "version": "1.12.0", + "version": "1.13.0", "author": "F5 Networks", "license": "Apache-2.0", "repository": { @@ -125,7 +125,8 @@ "1070207", "1070443", "1075674", - "1070440" + "1070440", + "1082433" ] } } diff --git a/specs/openapi.yaml b/specs/openapi.yaml index f4156f7b..a2473563 100644 --- a/specs/openapi.yaml +++ b/specs/openapi.yaml @@ -1,6 +1,6 @@ openapi: "3.0.0" info: - version: 1.12.0 + version: 1.13.0 title: Cloud Failover (CF) Extension description: F5 Cloud Failover (CFE) is an iControl LX Extension delivered as a TMOS-independent RPM file. Installing the CFE Extension on BIG-IP enables you to declaratively configure BIG-IP devices for automatic failover in cloud environments by POSTing a single JSON declaration to CF’s declarative REST API endpoint. license: @@ -21,9 +21,9 @@ paths: schema: $ref: "#/components/schemas/InformationResponse" example: - version: "1.12.0" + version: "1.13.0" release: "1" - schemaCurrent: "1.12.0" + schemaCurrent: "1.13.0" schemaMinimum: "0.9.1" default: description: Unexpected Error diff --git a/src/nodejs/failover.js b/src/nodejs/failover.js index e3b90eb6..85ec2298 100644 --- a/src/nodejs/failover.js +++ b/src/nodejs/failover.js @@ -282,6 +282,7 @@ class FailoverClient { const customEnvironmentSettings = util.getDataByKey(this.config, 'customEnvironment') || []; let routeGroupDefinitions = util.getDataByKey(this.config, 'failoverRoutes.routeGroupDefinitions') || []; const trustedCertBundle = util.getDataByKey(this.config, 'trustedCertBundle') || ''; + const storageEncryption = util.getDataByKey(this.config, 'externalStorage.encryption') || []; const routeTags = util.getDataByKey(this.config, 'failoverRoutes.scopingTags') || []; const routeAddressRanges = (util.getDataByKey( this.config, 'failoverRoutes.scopingAddressRanges' @@ -312,6 +313,7 @@ class FailoverClient { customEnvironment: customEnvironmentSettings, routeGroupDefinitions, trustedCertBundle, + storageEncryption, storageTags: util.getDataByKey(this.config, 'externalStorage.scopingTags'), storageName: util.getDataByKey(this.config, 'externalStorage.scopingName'), subscriptions: (util.getDataByKey( diff --git a/src/nodejs/providers/abstract/cloud.js b/src/nodejs/providers/abstract/cloud.js index 667514e0..1298530b 100644 --- a/src/nodejs/providers/abstract/cloud.js +++ b/src/nodejs/providers/abstract/cloud.js @@ -54,6 +54,7 @@ class AbstractCloud { * { 'type': 'address': 'items': [], tag: null} * @param {Object} [options.storageTags] - storage tags to filter on { 'key': 'value' } * @param {Object} [options.storageName] - storage scoping name + * @param {Object} [options.storageEncryption] - storage encryption options * @param {Object} [options.subnets] - subnets * @param {Object} [options.trustedCertBundle] - custom certificate bundle for cloud API calls */ @@ -66,6 +67,7 @@ class AbstractCloud { this.routeGroupDefinitions = options.routeGroupDefinitions || {}; this.storageTags = options.storageTags || {}; this.storageName = options.storageName || ''; + this.storageEncryption = options.storageEncryption || null; this.subnets = options.subnets || {}; this.trustedCertBundle = options.trustedCertBundle || ''; } diff --git a/src/nodejs/providers/aws/cloud.js b/src/nodejs/providers/aws/cloud.js index 344ec7e7..4e320efb 100644 --- a/src/nodejs/providers/aws/cloud.js +++ b/src/nodejs/providers/aws/cloud.js @@ -132,6 +132,14 @@ class Cloud extends AbstractCloud { Bucket: this.s3BucketName, Key: s3Key }; + if (this.storageEncryption + && this.storageEncryption.serverSide + && this.storageEncryption.serverSide.enabled) { + params.ServerSideEncryption = this.storageEncryption.serverSide.algorithm; + if (this.storageEncryption.serverSide.keyId) { + params.SSEKMSKeyId = this.storageEncryption.serverSide.keyId; + } + } this.s3.putObject(params).promise() .then(() => resolve()) .catch((err) => reject(err)); diff --git a/src/nodejs/schema/base_schema.json b/src/nodejs/schema/base_schema.json index 2cbb1026..76eb8928 100644 --- a/src/nodejs/schema/base_schema.json +++ b/src/nodejs/schema/base_schema.json @@ -117,6 +117,7 @@ "type": "string", "$comment": "IMPORTANT: In enum array, please put current schema version first, oldest-supported version last. Keep enum array sorted most-recent-first.", "enum": [ + "1.13.0", "1.12.0", "1.11.0", "1.10.0", @@ -134,7 +135,7 @@ "1.0.0", "0.9.1" ], - "default": "1.12.0" + "default": "1.13.0" }, "$schema": { "title": "Schema", @@ -280,6 +281,39 @@ "title": "External Storage", "description": "External storage this deployment will manage.", "type": "object", + "properties": { + "encryption": { + "description": "Settings related to encrypted storage.", + "type": "object", + "properties": { + "serverSide": { + "description": "Settings related to server-side encryption.", + "type": "object", + "properties": { + "enabled": { + "description": "For enabling server-side encryption.", + "type": "boolean", + "default": false + }, + "algorithm": { + "description": "Encryption algorithm used for server-side encryption.", + "type": "string", + "enum": [ + "AES256", + "aws:kms" + ], + "default": "aws:kms" + }, + "keyId": { + "description": "Client-managed key ID used for server-side encryption.", + "type": "string", + "examples": ["myKeyId"] + } + } + } + } + } + }, "oneOf": [ { "properties": { diff --git a/test/functional/tests/providers/azure/tests.js b/test/functional/tests/providers/azure/tests.js index b09ee0ce..da5a57b8 100644 --- a/test/functional/tests/providers/azure/tests.js +++ b/test/functional/tests/providers/azure/tests.js @@ -45,7 +45,7 @@ function networkInterfaceMatch(networkInterfaces, selfIps, virtualAddresses) { networkInterfaces.forEach((nic) => { nic.ipConfigurations.forEach((ipConfiguration) => { selfIps.forEach((address) => { - if (ipConfiguration.privateIPAddress === address) { + if (nic.provisioningState === 'Succeeded' && ipConfiguration.primary === true && ipConfiguration.privateIPAddress === address) { myNics.push(nic); } }); @@ -55,7 +55,7 @@ function networkInterfaceMatch(networkInterfaces, selfIps, virtualAddresses) { myNics.forEach((nic) => { nic.ipConfigurations.forEach((ipConfiguration) => { virtualAddresses.forEach((address) => { - if (ipConfiguration.privateIPAddress === address && nic.provisioningState === 'Succeeded') { + if (nic.provisioningState === 'Succeeded' && ipConfiguration.primary === false && ipConfiguration.privateIPAddress === address) { match = true; } }); diff --git a/test/unit/providers/awsProviderTests.js b/test/unit/providers/awsProviderTests.js index f24a847c..4bfe8f92 100644 --- a/test/unit/providers/awsProviderTests.js +++ b/test/unit/providers/awsProviderTests.js @@ -549,6 +549,7 @@ describe('Provider - AWS', () => { assert.fail(); })); }); + describe('function _getPrivateSecondaryIPs', () => { const describeNetworkInterfacesResponse = { NetworkInterfaces: [ @@ -654,6 +655,7 @@ describe('Provider - AWS', () => { }); }); }); + describe('function _generatePublicAddressOperations', () => { const EIPdata = [ { @@ -691,6 +693,7 @@ describe('Provider - AWS', () => { assert.fail(); })); }); + describe('function _associatePublicAddress', () => { const allocationId = 'eipalloc-0b5671ebba3628edd'; const networkInterfaceId = 'eni-0157ac0f9506af78b'; @@ -744,6 +747,7 @@ describe('Provider - AWS', () => { }); }); }); + describe('function _disassociatePublicAddress', () => { let passedParams; const associationIdToDisassociate = 'eipassoc-00523b2b8b8c01793'; @@ -770,6 +774,7 @@ describe('Provider - AWS', () => { assert.fail(); })); }); + describe('function _reassociatePublicAddresses', () => { it('should call _disassociatePublicAddress with correct params', () => { const passedParams = []; @@ -1543,8 +1548,15 @@ describe('Provider - AWS', () => { describe('function uploadDataToStorage', () => { let passedParams; + const thisMockInitData = { + storageEncryption: { + serverSide: { + enabled: false + } + } + }; - it('should pass correct params to putObject', () => provider.init(mockInitData) + it('should pass correct params to putObject', () => provider.init(thisMockInitData) .then(() => { provider.s3BucketName = 'myfailoverbucket'; @@ -1567,6 +1579,90 @@ describe('Provider - AWS', () => { })); }); + describe('function uploadDataToStorage encrypted with AWS managed key', () => { + let passedParams; + const _s3FileParamsStubEncrypted = { + Body: 's3 state file body', + Bucket: 'myfailoverbucket', + Key: 'f5cloudfailover/file.json', + ServerSideEncryption: 'aws:kms' + }; + + const thisMockInitData = { + storageEncryption: { + serverSide: { + enabled: true, + algorithm: 'aws:kms' + } + } + }; + + it('should pass correct params to putObject with AWS managed key', () => provider.init(thisMockInitData) + .then(() => { + provider.s3BucketName = 'myfailoverbucket'; + + provider.s3.putObject = sinon.stub() + .callsFake((params) => { + passedParams = params; + return { + promise() { + return Promise.resolve(); + } + }; + }); + return provider.uploadDataToStorage('file.json', _s3FileParamsStubEncrypted.Body); + }) + .then(() => { + assert.deepEqual(passedParams, _s3FileParamsStubEncrypted); + }) + .catch(() => { + assert.fail(); + })); + }); + + describe('function uploadDataToStorage encrypted with customer key', () => { + let passedParams; + const _s3FileParamsStubEncryptedCustomerKey = { + Body: 's3 state file body', + Bucket: 'myfailoverbucket', + Key: 'f5cloudfailover/file.json', + ServerSideEncryption: 'aws:kms', + SSEKMSKeyId: 'mrk-e6113680390641cab86a87e821e43764' + }; + + const thisMockInitData = { + storageEncryption: { + serverSide: { + enabled: true, + algorithm: 'aws:kms', + keyId: 'mrk-e6113680390641cab86a87e821e43764' + } + } + }; + + it('should pass correct params to putObject with customer key', () => provider.init(thisMockInitData) + .then(() => { + provider.s3BucketName = 'myfailoverbucket'; + + provider.s3.putObject = sinon.stub() + .callsFake((params) => { + passedParams = params; + return { + promise() { + return Promise.resolve(); + } + }; + }); + return provider.uploadDataToStorage('file.json', _s3FileParamsStubEncryptedCustomerKey.Body); + }) + .then(() => { + assert.deepEqual(passedParams, _s3FileParamsStubEncryptedCustomerKey); + }) + .catch(() => { + assert.fail(); + })); + }); + describe('function downloadDataFromStorage', () => { let passedParams; const mockResponseBody = { foo: 'bar' }; From a70027eebabc45632e245ab52014402cdc37e728 Mon Sep 17 00:00:00 2001 From: Michael Shimkus Date: Mon, 12 Sep 2022 19:43:13 +0000 Subject: [PATCH 2/7] AUTOSDK-583 - Fix Azure address group definition failover --- deployment-tool | 2 +- src/nodejs/providers/azure/cloud.js | 55 ++++++----- test/unit/providers/azureProviderTests.js | 107 +++++++++++++++++++--- 3 files changed, 128 insertions(+), 36 deletions(-) diff --git a/deployment-tool b/deployment-tool index 2e673f24..24eca466 160000 --- a/deployment-tool +++ b/deployment-tool @@ -1 +1 @@ -Subproject commit 2e673f24f60e150c572e8655644549c2216430ac +Subproject commit 24eca4665fa7ac877cd8aa9c9dae97c99bcc41df diff --git a/src/nodejs/providers/azure/cloud.js b/src/nodejs/providers/azure/cloud.js index 1aaff165..88a30a7a 100644 --- a/src/nodejs/providers/azure/cloud.js +++ b/src/nodejs/providers/azure/cloud.js @@ -503,7 +503,7 @@ class Cloud extends AbstractCloud { let matchedTags = 0; tagKeys.forEach((tagKey) => { if (sa.tags && Object.keys(sa.tags).indexOf(tagKey) !== -1 - && sa.tags[tagKey] === tags[tagKey]) { + && sa.tags[tagKey] === tags[tagKey]) { matchedTags += 1; } }); @@ -804,6 +804,8 @@ class Cloud extends AbstractCloud { const theirNicIpConfigs = this._getIpConfigs(theirNic.ipConfigurations); const myNicIpConfigs = this._getIpConfigs(myNic.ipConfigurations); + this.logger.silly('checking for NIC operations for my/their NIC pair:', myNic.name, theirNic.name); + for (let i = theirNicIpConfigs.length - 1; i >= 0; i -= 1) { for (let t = failoverAddresses.length - 1; t >= 0; t -= 1) { if (failoverAddresses[t] === theirNicIpConfigs[i].privateIPAddress) { @@ -1119,6 +1121,7 @@ class Cloud extends AbstractCloud { * @returns {Promise} - A Promise that is resolved network interface operations */ _generateNetworkInterfaceOperations(addresses, addressGroupDefinitions) { + const failoverAddresses = []; const operations = { disassociate: [], associate: [] @@ -1129,27 +1132,37 @@ class Cloud extends AbstractCloud { .then((results) => { const nics = results[0]; addressGroupDefinitions.forEach((item) => { - const failoverAddresses = [item.scopingAddress]; - const parsedNics = this._parseNics(nics, addresses.localAddresses, failoverAddresses); - if (parsedNics.mine.length === 0 || parsedNics.theirs.length === 0) { - this.logger.warning('Problem with discovering network interfaces parsedNics'); - return Promise.resolve({ - publicAddresses: {}, - interfaces: operations, - loadBalancerAddresses: {} - }); - } - const nicOperations = this._checkForNicOperations( - parsedNics.mine[0].nic, - parsedNics.theirs[0].nic, - failoverAddresses - ); - if (nicOperations.disassociate && nicOperations.associate) { - operations.disassociate.push(nicOperations.disassociate); - operations.associate.push(nicOperations.associate); - } - return item; + failoverAddresses.push(item.scopingAddress); }); + const parsedNics = this._parseNics(nics, addresses.localAddresses, failoverAddresses); + if (parsedNics.mine.length === 0 || parsedNics.theirs.length === 0) { + this.logger.warning('Problem with discovering network interfaces parsedNics'); + return Promise.resolve({ + publicAddresses: {}, + interfaces: operations, + loadBalancerAddresses: {} + }); + } + for (let s = parsedNics.mine.length - 1; s >= 0; s -= 1) { + for (let h = parsedNics.theirs.length - 1; h >= 0; h -= 1) { + const theirNic = parsedNics.theirs[h].nic; + const myNic = parsedNics.mine[s].nic; + theirNic.tags = theirNic.tags ? theirNic.tags : this._normalizeTags(theirNic.TagSet); + myNic.tags = myNic.tags ? myNic.tags : this._normalizeTags(myNic.TagSet); + /* eslint-disable max-len */ + if (theirNic.tags[constants.NIC_TAG] === undefined || myNic.tags[constants.NIC_TAG] === undefined) { + this.logger.warning(`${constants.NIC_TAG} tag values do not match or doesn't exist for a interface`); + } else if (theirNic.tags[constants.NIC_TAG] && myNic.tags[constants.NIC_TAG] + && theirNic.tags[constants.NIC_TAG] === myNic.tags[constants.NIC_TAG]) { + const nicOperations = this._checkForNicOperations(myNic, theirNic, failoverAddresses); + + if (nicOperations.disassociate && nicOperations.associate) { + operations.disassociate.push(nicOperations.disassociate); + operations.associate.push(nicOperations.associate); + } + } + } + } this.resultAction.interfaces = operations; return Promise.resolve(); }) diff --git a/test/unit/providers/azureProviderTests.js b/test/unit/providers/azureProviderTests.js index b4dc9e68..5ffa49e1 100644 --- a/test/unit/providers/azureProviderTests.js +++ b/test/unit/providers/azureProviderTests.js @@ -369,6 +369,7 @@ describe('Provider - Azure', () => { }) .catch((err) => Promise.reject(err)); }); + it('should validate updateAddresses does not perform discovery due to mismatched nic tags', () => { const localAddresses = ['2.2.2.2']; const failoverAddresses = ['10.10.10.10']; @@ -422,6 +423,7 @@ describe('Provider - Azure', () => { }) .catch((err) => Promise.reject(err)); }); + it('validate _updateNic promise callback for valid case', () => { provider.primarySubscriptionId = mockSubscriptionId; provider.networkClients[mockSubscriptionId] = sinon.stub(); @@ -1383,7 +1385,7 @@ describe('Provider - Azure', () => { failoverAddresses: [] }; const addresses2 = { - localAddresses: ['10.10.10.4'], + localAddresses: ['10.10.10.4', '10.10.11.4'], failoverAddresses: [] }; // Use nic01 and nic02 to validate across-net, @@ -1433,7 +1435,7 @@ describe('Provider - Azure', () => { } ] }; - // Use nic03 and nic04 to validate same-net, moving the secondary ipConfigurations + // Use nic03-nic06 to validate same-net, moving the secondary ipConfigurations const nic03 = { id: 'test-nic03', name: 'nic03', @@ -1464,7 +1466,11 @@ describe('Provider - Azure', () => { }, provisioningState: 'Succeeded' } - ] + ], + tags: { + f5_cloud_failover_label: 'tagsNic', + f5_cloud_failover_nic_map: 'external' + } }; const nic04 = { id: 'test-nic04', @@ -1480,7 +1486,55 @@ describe('Provider - Azure', () => { }, provisioningState: 'Succeeded' } - ] + ], + tags: { + f5_cloud_failover_label: 'tagsNic', + f5_cloud_failover_nic_map: 'external' + } + }; + const nic05 = { + id: 'test-nic05', + name: 'nic05', + provisioningState: 'Succeeded', + type: 'networkInterfaces', + ipConfigurations: [ + { + privateIPAddress: '10.10.11.3', + primary: true, + provisioningState: 'Succeeded' + }, + { + privateIPAddress: '10.10.11.20', + primary: false, + provisioningState: 'Succeeded' + }, + { + privateIPAddress: '10.10.11.21', + primary: false, + provisioningState: 'Succeeded' + } + ], + tags: { + f5_cloud_failover_label: 'tagsNic', + f5_cloud_failover_nic_map: 'internal' + } + }; + const nic06 = { + id: 'test-nic06', + name: 'nic06', + provisioningState: 'Succeeded', + type: 'networkInterfaces', + ipConfigurations: [ + { + privateIPAddress: '10.10.11.4', + primary: true, + provisioningState: 'Succeeded' + } + ], + tags: { + f5_cloud_failover_label: 'tagsNic', + f5_cloud_failover_nic_map: 'internal' + } }; const publicIpResponse = { id: 'vip-pip1', @@ -1602,28 +1656,53 @@ describe('Provider - Azure', () => { 'nic03', 'nic04' ] + }, + { + type: 'networkInterfaceAddress', + scopingAddress: '10.10.11.20', + networkInterfaces: [ + 'nic05', + 'nic06' + ] + }, + { + type: 'networkInterfaceAddress', + scopingAddress: '10.10.11.21', + networkInterfaces: [ + 'nic05', + 'nic06' + ] } ]; provider.primarySubscriptionId = mockSubscriptionId; provider.networkClients[mockSubscriptionId] = sinon.stub(); provider.networkClients[mockSubscriptionId].networkInterfaces = sinon.stub(); provider.networkClients[mockSubscriptionId].networkInterfaces.list = sinon.stub((error, callback) => { - callback(error, [nic03, nic04]); + callback(error, [nic03, nic04, nic05, nic06]); }); return provider.discoverAddressOperationsUsingDefinitions(addresses2, networkGroupDefinitions, options) .then((response) => { const disasociate = response.interfaces.disassociate; const associate = response.interfaces.associate; - assert.strictEqual(disasociate[0][1], 'nic03'); - assert.strictEqual(disasociate[0][2].name, 'nic03'); - assert.strictEqual(disasociate[0][2].ipConfigurations[0].privateIPAddress, '10.10.10.3'); - assert.strictEqual(associate[0][1], 'nic04'); - assert.strictEqual(associate[0][2].name, 'nic04'); - assert.strictEqual(associate[0][2].ipConfigurations[0].privateIPAddress, '10.10.10.4'); - assert.strictEqual(associate[0][2].ipConfigurations[1].privateIPAddress, '10.10.10.20'); - assert.strictEqual(associate[0][2].ipConfigurations[2].privateIPAddress, '10.10.10.21'); - assert.strictEqual(associate[0][2].ipConfigurations[1].publicIPAddress.id, 'vip-pip6'); + assert.strictEqual(disasociate[1][1], 'nic03'); + assert.strictEqual(disasociate[1][2].name, 'nic03'); + assert.strictEqual(disasociate[1][2].ipConfigurations[0].privateIPAddress, '10.10.10.3'); + assert.strictEqual(associate[1][1], 'nic04'); + assert.strictEqual(associate[1][2].name, 'nic04'); + assert.strictEqual(associate[1][2].ipConfigurations[0].privateIPAddress, '10.10.10.4'); + assert.strictEqual(associate[1][2].ipConfigurations[1].privateIPAddress, '10.10.10.21'); + assert.strictEqual(associate[1][2].ipConfigurations[2].privateIPAddress, '10.10.10.20'); + assert.strictEqual(associate[1][2].ipConfigurations[1].publicIPAddress.id, 'vip-pip7'); + assert.strictEqual(associate[1][2].ipConfigurations[2].publicIPAddress.id, 'vip-pip6'); + assert.strictEqual(disasociate[0][1], 'nic05'); + assert.strictEqual(disasociate[0][2].name, 'nic05'); + assert.strictEqual(disasociate[0][2].ipConfigurations[0].privateIPAddress, '10.10.11.3'); + assert.strictEqual(associate[0][1], 'nic06'); + assert.strictEqual(associate[0][2].name, 'nic06'); + assert.strictEqual(associate[0][2].ipConfigurations[0].privateIPAddress, '10.10.11.4'); + assert.strictEqual(associate[0][2].ipConfigurations[1].privateIPAddress, '10.10.11.21'); + assert.strictEqual(associate[0][2].ipConfigurations[2].privateIPAddress, '10.10.11.20'); }) .catch((err) => Promise.reject(err)); }); From 13246f84ddab2ab66218b147d443aa798bda8ad4 Mon Sep 17 00:00:00 2001 From: Alex Applebaum Date: Tue, 13 Sep 2022 00:01:45 +0000 Subject: [PATCH 3/7] 3157 doc --- docs/userguide/aws-same-az.rst | 105 +++++++++++++----- docs/userguide/aws.rst | 81 +++++++++++--- docs/userguide/example-declarations.rst | 18 +-- .../declarations/aws-across-az-1.13.0.json | 61 ++++++++++ ...aws-s3-server-side-encryption-aws-key.json | 38 +++++-- ...-s3-server-side-encryption-custom-key.json | 36 ++++-- examples/declarations/aws-same-az-1.13.0.json | 53 +++++++++ 7 files changed, 320 insertions(+), 72 deletions(-) create mode 100644 examples/declarations/aws-across-az-1.13.0.json create mode 100644 examples/declarations/aws-same-az-1.13.0.json diff --git a/docs/userguide/aws-same-az.rst b/docs/userguide/aws-same-az.rst index c051c4fb..1fc344a0 100644 --- a/docs/userguide/aws-same-az.rst +++ b/docs/userguide/aws-same-az.rst @@ -79,13 +79,13 @@ Example AWS Declaration ----------------------- This example declaration shows the minimum information needed to update the cloud resources in AWS. See the :ref:`quickstart` section for steps on how to post this declaration. See the :ref:`example-declarations` section for more examples. -.. literalinclude:: ../../examples/declarations/aws-same-az-1.7.0.json +.. literalinclude:: ../../examples/declarations/aws-same-az-1.13.0.json :language: json :caption: Example AWS Declaration with Single Routing Table :tab-width: 4 :linenos: -:fonticon:`fa fa-download` :download:`aws-same-az.json <../../examples/declarations/aws-same-az-1.7.0.json>` +:fonticon:`fa fa-download` :download:`aws-same-az.json <../../examples/declarations/aws-same-az-1.13.0.json>` | @@ -125,11 +125,12 @@ In order to successfully implement CFE in AWS, you need an AWS Identity and Acce s3:ListAllMyBuckets \* Current Account externalStorage To discover (using scopingTags) bucket used for failover state file. s3:ListBucket S3 Bucket ID Optional externalStorage To return information about a bucket. s3:PutObject S3 Bucket ID/Key Optional externalStorage To write failover state file. - kms:DescribeKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. - kms:GenerateDataKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. - kms:Decrypt KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. + kms:DescribeKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a **customer managed** KMS key for server-side encryption. + kms:GenerateDataKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a **customer managed** KMS key for server-side encryption. + kms:Decrypt KMS Encryption Key ID Optional externalStorage To write failover state file when using a **customer managed** KMS key for server-side encryption. ======================================== ============================== ======================= ======================= ===================================================================================================================== - | + + | For example, to create a role for an EC2 service follow these steps: @@ -153,7 +154,7 @@ In order to successfully implement CFE in AWS, you need an AWS Identity and Acce | -#. Assign an IAM role to each instance by navigating to **EC2 > Instances > Instance > Actions > Instance Settings > Attach/Replace IAM Role** +2. Assign an IAM role to each instance by navigating to **EC2 > Instances > Instance > Actions > Instance Settings > Attach/Replace IAM Role** For example: @@ -164,8 +165,6 @@ In order to successfully implement CFE in AWS, you need an AWS Identity and Acce .. _aws-same-az-iam-example: -.. _aws-iam-example: - IAM Role Example Declaration ```````````````````````````` Below is an example F5 policy that includes IAM roles. @@ -175,7 +174,7 @@ Below is an example F5 policy that includes IAM roles. .. code-block:: json - { + { "BigIpHighAvailabilityAccessRole": { "Condition": "failover", "Type": "AWS::IAM::Role", @@ -233,6 +232,26 @@ Below is an example F5 policy that includes IAM roles. ], "Resource": "arn:*:s3:::/*" }, + { + "Action": [ + "s3:PutObject" + ], + "Condition": { + "Null": { + "s3:x-amz-server-side-encryption": true + } + }, + "Effect": "Deny", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:*:s3:::/*" + ] + ] + }, + "Sid": "DenyPublishingUnencryptedResources" + }, { "Effect": "Allow", "Action": [ @@ -322,12 +341,27 @@ Below is an example F5 policy that includes IAM roles. ] } } - } + } | +NOTE: If a customer managed KMS Encryption Key is used for server-side encryption on the S3 bucket, the following permissions are required: + +.. code-block:: json + + { + "Effect": "Allow", + "Action": [ + "kms:DescribeKey", + "kms:GenerateDataKey", + "kms:Decrypt" + ], + "Resource": "arn:aws:kms:::key/" + }, + +| -Alternatively, for *Actions* that **do** allow resource level permissions, but the specific resource IDs may not be known ahead of time, you can leverage *Condition* statements that limit access to only those resources with a certain tag. For example, in some orchestration workflows, the IAM instance profile and policy are created first in order to apply to the instance at creation time, but the of course the instance IDs for the policy are not known yet. Instead, in the snippet below, *Conditions* are used so only resources with the `f5_cloud_failover_label` tag can be updated. +Alternatively, for *Actions* that **do** allow resource level permissions, but the specific resource IDs may not be known ahead of time, you can leverage *Condition* statements that limit access to only those resources with a certain tag. For example, in some orchestration workflows, the IAM instance profile and policy are created first in order to apply to the instance at creation time, but of course the instance IDs for the policy are not known yet. Instead, in the snippet below, *Conditions* are used so only resources with the ``f5_cloud_failover_label`` tag can be updated. .. code-block:: json @@ -426,34 +460,51 @@ Tag the Network Interfaces in AWS: Define the Storage Account in AWS ````````````````````````````````` -1. Create an `S3 bucket in AWS `_ for Cloud Failover Extension cluster-wide file(s). - - .. WARNING:: To avoid a potential data breach, ensure the required S3 buckets are properly secured and do not have public access. See your cloud provider for best practices. - - .. sidebar:: :fonticon:`fa fa-info-circle fa-lg` Version Notice: + + - The property ``scopingName`` is available in Cloud Failover Extension v1.7.0 and later. + - Beginning v1.13.0, CFE supports Serverside Encryption on the S3 Bucket using AWS KMS (SSE-KMS) with either the default AWS managed key or a customer managed key. See `AWS Documentation `_ for more details on how to enable server-side encryption on the S3 bucket. + + +1. Create an `S3 bucket in AWS `_ for Cloud Failover Extension cluster-wide file(s). - The property ``scopingName`` is available in Cloud Failover Extension v1.7.0 and later. + .. WARNING:: To avoid a potential data breach, ensure the required S3 buckets are properly secured and do not have public access. See your cloud provider for best practices. + 2. Update/modify the Cloud Failover ``scopingName`` value with name of your S3 bucket: .. code-block:: json + :emphasize-lines: 2 - "externalStorage":{ - "scopingName": "yourS3BucketforCloudFailover" - }, - + "externalStorage":{ + "scopingName": "yourS3BucketforCloudFailover", + "encryption": { + "serverSide": { + "enabled": true, + "algorithm": "aws:kms" + } + } + }, + You can also optionally update/modify the serverside encyption config. See Click `here `_ to see an example using a customer managed key. Alternatively, if you are using the Discovery via Tag option, tag the S3 bucket with your custom key:values in the `externalStorage.scopingTags` section of the CFE declaration. .. code-block:: json + :emphasize-lines: 3 + + "externalStorage":{ + "scopingTags":{ + "f5_cloud_failover_label":"mydeployment" + }, + "encryption": { + "serverSide": { + "enabled": true, + "algorithm": "aws:kms" + } + } + }, - "externalStorage":{ - "scopingTags":{ - "f5_cloud_failover_label":"mydeployment" - } - }, a. Sign in to the AWS Management Console and open the Amazon S3 console. diff --git a/docs/userguide/aws.rst b/docs/userguide/aws.rst index 7276fe96..6822cbfd 100644 --- a/docs/userguide/aws.rst +++ b/docs/userguide/aws.rst @@ -79,13 +79,13 @@ Example AWS Declaration ----------------------- This example declaration shows a configuration used for the diagram above. See the :ref:`quickstart` section for steps on how to post this declaration. See the :ref:`example-declarations` section for more examples. -.. literalinclude:: ../../examples/declarations/aws-across-az-1.7.0.json +.. literalinclude:: ../../examples/declarations/aws-across-az-1.13.0.json :language: json :caption: Example AWS Declaration with Single Routing Table :tab-width: 4 :linenos: -:fonticon:`fa fa-download` :download:`aws.json <../../examples/declarations/aws-across-az-1.7.0.json>` +:fonticon:`fa fa-download` :download:`aws.json <../../examples/declarations/aws-across-az-1.13.0.json>` | @@ -121,9 +121,9 @@ In order to successfully implement CFE in AWS, you need an AWS Identity and Acce s3:ListAllMyBuckets \* Current Account externalStorage To discover (using scopingTags) bucket used for failover state file. s3:ListBucket S3 Bucket ID Optional externalStorage To return information about a bucket. s3:PutObject S3 Bucket ID/Key Optional externalStorage To write failover state file. - kms:DescribeKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. - kms:GenerateDataKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. - kms:Decrypt KMS Encryption Key ID Optional externalStorage To write failover state file when using a customer-managed KMS key for server-side encryption. + kms:DescribeKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a **customer managed** KMS key for server-side encryption. + kms:GenerateDataKey KMS Encryption Key ID Optional externalStorage To write failover state file when using a **customer managed** KMS key for server-side encryption. + kms:Decrypt KMS Encryption Key ID Optional externalStorage To write failover state file when using a **customer managed** KMS key for server-side encryption. ======================================== ============================== ======================= ======================= ===================================================================================================================== | @@ -227,6 +227,26 @@ Below is an example F5 policy that includes IAM roles. ], "Resource": "arn:*:s3:::/*" }, + { + "Action": [ + "s3:PutObject" + ], + "Condition": { + "Null": { + "s3:x-amz-server-side-encryption": true + } + }, + "Effect": "Deny", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:*:s3:::/*" + ] + ] + }, + "Sid": "DenyPublishingUnencryptedResources" + }, { "Effect": "Allow", "Action": [ @@ -316,6 +336,22 @@ Below is an example F5 policy that includes IAM roles. | +NOTE: If a customer managed KMS Encryption Key is used for server-side encryption on the S3 bucket, the following permissions are required: + +.. code-block:: json + + { + "Effect": "Allow", + "Action": [ + "kms:DescribeKey", + "kms:GenerateDataKey", + "kms:Decrypt" + ], + "Resource": "arn:aws:kms:::key/" + }, + +| + Alternatively, for *Actions* that **do** allow resource level permissions, but the specific resource IDs may not be known ahead of time, you can leverage *Condition* statements that limit access to only those resources with a certain tag. For example, in some orchestration workflows, the IAM instance profile and policy are created first in order to apply to the instance at creation time, but the of course the instance IDs for the policy are not known yet. Instead, in the snippet below, *Conditions* are used so only resources with the `f5_cloud_failover_label` tag can be updated. .. code-block:: json @@ -403,36 +439,53 @@ Tag the Network Interfaces in AWS: Define the Storage Account in AWS ````````````````````````````````` +.. sidebar:: :fonticon:`fa fa-info-circle fa-lg` Version Notice: -1. Create an `S3 bucket in AWS `_ for Cloud Failover Extension cluster-wide file(s). + - The property ``scopingName`` is available in Cloud Failover Extension v1.7.0 and later. + - Beginning v1.13.0, CFE supports Serverside Encryption on the S3 Bucket using AWS KMS (SSE-KMS) with either the default AWS managed key or a customer managed key. See `AWS Documentation `_ for more details on how to enable server-side encryption on the S3 bucket. + + +1. Create an `S3 bucket in AWS `_ for Cloud Failover Extension cluster-wide file(s). + .. WARNING:: To avoid a potential data breach, ensure the required S3 buckets are properly secured and do not have public access. See your cloud provider for best practices. -.. sidebar:: :fonticon:`fa fa-info-circle fa-lg` Version Notice: - - The property ``scopingName`` is available in Cloud Failover Extension v1.7.0 and later. 2. Update/modify the Cloud Failover ``scopingName`` value with name of your S3 bucket: .. code-block:: json + :emphasize-lines: 2 - "externalStorage":{ - "scopingName": "yourS3BucketforCloudFailover" - }, - - | + "externalStorage":{ + "scopingName": "yourS3BucketforCloudFailover", + "encryption": { + "serverSide": { + "enabled": true, + "algorithm": "aws:kms" + } + } + }, + You can also optionally update/modify the serverside encyption config. See Click `here `_ to see an example using a customer managed key. Alternatively, if you are using the Discovery via Tag option, tag the S3 bucket with your custom key:values in the `externalStorage.scopingTags` section of the CFE declaration. .. code-block:: json + :emphasize-lines: 3 "externalStorage":{ "scopingTags":{ "f5_cloud_failover_label":"mydeployment" + }, + "encryption": { + "serverSide": { + "enabled": true, + "algorithm": "aws:kms" + } } }, + a. Sign in to the AWS Management Console and open the Amazon S3 console. b. In the :guilabel:`Bucket name` list, choose the name of the bucket. diff --git a/docs/userguide/example-declarations.rst b/docs/userguide/example-declarations.rst index da6101c2..89ba4bf7 100644 --- a/docs/userguide/example-declarations.rst +++ b/docs/userguide/example-declarations.rst @@ -123,8 +123,8 @@ This example shows a BIG-IP cluster managing route tables in multiple subscripti .. _aws-sse-aws-key: -Example Declaration Using AWS S3 Server-side encryption - AWS managed key -------------------------------------------------------------------------- +AWS KMS Server-side encryption (SSE-KMS) Using Default AWS Managed Key +---------------------------------------------------------------------- This example shows how to configure CFE when the S3 bucket used for failover state uses server-side KMS encryption with the default AWS managed key. .. literalinclude:: ../../examples/declarations/aws-s3-server-side-encryption-aws-key.json @@ -132,27 +132,27 @@ This example shows how to configure CFE when the S3 bucket used for failover sta :caption: AWS Server-side encryption with AWS managed key :tab-width: 4 :linenos: + :emphasize-lines: 10-15 :fonticon:`fa fa-download` :download:`aws-s3-server-side-encryption-aws-key.json <../../examples/declarations/aws-s3-server-side-encryption-aws-key.json>` .. _aws-sse-custom-key: -Example Declaration Using AWS S3 Server-side encryption - Custom key --------------------------------------------------------------------- -This example shows how to configure CFE when the S3 bucket used for failover state uses server-side KMS encryption with a customer-provided key. - -AWS S3 Server-side encryption - Custom key +AWS KMS Server-side encryption (SSE-KMS) Using Customer Managed Key +------------------------------------------------------------------- +This example shows how to configure CFE when the S3 bucket used for failover state uses server-side KMS encryption with a customer-provided key. Note: The ``keyId`` should be the actual ID, not the `arn` or `alias`. .. literalinclude:: ../../examples/declarations/aws-s3-server-side-encryption-custom-key.json :language: json :caption: AWS Server-side encryption with custom key :tab-width: 4 :linenos: + :emphasize-lines: 12-18 :fonticon:`fa fa-download` :download:`aws-s3-server-side-encryption-custom-key.json <../../examples/declarations/aws-s3-server-side-encryption-custom-key.json>` -Example Declaration Setting the Log Level ------------------------------------------ +Setting the Log Level +--------------------- You set the log level in the controls class. To see more information about editing the controls class, see :ref:`logging-ref`. diff --git a/examples/declarations/aws-across-az-1.13.0.json b/examples/declarations/aws-across-az-1.13.0.json new file mode 100644 index 00000000..3d6dafe2 --- /dev/null +++ b/examples/declarations/aws-across-az-1.13.0.json @@ -0,0 +1,61 @@ +{ + "class": "Cloud_Failover", + "environment": "aws", + "controls": { + "class": "Controls", + "logLevel": "silly" + }, + "externalStorage": { + "scopingName": "myCloudFailoverBucket" + }, + "failoverAddresses": { + "enabled": true, + "scopingTags": { + "f5_cloud_failover_label": "mydeployment", + "encryption": { + "serverSide": { + "enabled": true, + "algorithm": "aws:kms" + } + } + }, + "addressGroupDefinitions": [ + { + "type": "elasticIpAddress", + "scopingAddress": "1.1.1.1", + "vipAddresses": [ + "10.0.12.101", + "10.0.22.101" + ] + }, + { + "type": "elasticIpAddress", + "scopingAddress": "2.2.2.2", + "vipAddresses": [ + "10.0.12.102", + "10.0.22.102" + ] + } + ] + }, + "failoverRoutes": { + "enabled": true, + "routeGroupDefinitions": [ + { + "scopingName": "rtb-11111111111111111", + "scopingAddressRanges": [ + { + "range": "0.0.0.0/0" + } + ], + "defaultNextHopAddresses": { + "discoveryType": "static", + "items": [ + "10.0.13.11", + "10.0.23.11" + ] + } + } + ] + } +} diff --git a/examples/declarations/aws-s3-server-side-encryption-aws-key.json b/examples/declarations/aws-s3-server-side-encryption-aws-key.json index 21dea8bd..c04b7705 100644 --- a/examples/declarations/aws-s3-server-side-encryption-aws-key.json +++ b/examples/declarations/aws-s3-server-side-encryption-aws-key.json @@ -6,9 +6,7 @@ "logLevel": "silly" }, "externalStorage": { - "scopingTags": { - "f5_cloud_failover_label": "mydeployment" - }, + "scopingName": "myCloudFailoverBucket", "encryption": { "serverSide": { "enabled": true, @@ -20,20 +18,36 @@ "enabled": true, "scopingTags": { "f5_cloud_failover_label": "mydeployment" - } + }, + "addressGroupDefinitions": [ + { + "type": "networkInterfaceAddress", + "scopingAddress": "10.0.12.101" + }, + { + "type": "networkInterfaceAddress", + "scopingAddress": "10.0.12.102" + } + ] }, "failoverRoutes": { "enabled": true, - "scopingTags": { - "f5_cloud_failover_label": "mydeployment" - }, - "scopingAddressRanges": [ + "routeGroupDefinitions": [ { - "range": "0.0.0.0/0", - "nextHopAddresses": { - "discoveryType": "routeTag" + "scopingName": "rtb-11111111111111111", + "scopingAddressRanges": [ + { + "range": "0.0.0.0/0" + } + ], + "defaultNextHopAddresses": { + "discoveryType": "static", + "items": [ + "10.0.13.11", + "10.0.13.12" + ] } } ] } -} +} \ No newline at end of file diff --git a/examples/declarations/aws-s3-server-side-encryption-custom-key.json b/examples/declarations/aws-s3-server-side-encryption-custom-key.json index cf9320d5..18bc85f8 100644 --- a/examples/declarations/aws-s3-server-side-encryption-custom-key.json +++ b/examples/declarations/aws-s3-server-side-encryption-custom-key.json @@ -13,7 +13,7 @@ "serverSide": { "enabled": true, "algorithm": "aws:kms", - "keyId": "myCustomKmsKey" + "keyId": "11111111-1111-1111-111-11111111111" } } }, @@ -21,20 +21,36 @@ "enabled": true, "scopingTags": { "f5_cloud_failover_label": "mydeployment" - } + }, + "addressGroupDefinitions": [ + { + "type": "networkInterfaceAddress", + "scopingAddress": "10.0.12.101" + }, + { + "type": "networkInterfaceAddress", + "scopingAddress": "10.0.12.102" + } + ] }, "failoverRoutes": { "enabled": true, - "scopingTags": { - "f5_cloud_failover_label": "mydeployment" - }, - "scopingAddressRanges": [ + "routeGroupDefinitions": [ { - "range": "0.0.0.0/0", - "nextHopAddresses": { - "discoveryType": "routeTag" + "scopingName": "rtb-11111111111111111", + "scopingAddressRanges": [ + { + "range": "0.0.0.0/0" + } + ], + "defaultNextHopAddresses": { + "discoveryType": "static", + "items": [ + "10.0.13.11", + "10.0.13.12" + ] } } ] } -} +} \ No newline at end of file diff --git a/examples/declarations/aws-same-az-1.13.0.json b/examples/declarations/aws-same-az-1.13.0.json new file mode 100644 index 00000000..35409f67 --- /dev/null +++ b/examples/declarations/aws-same-az-1.13.0.json @@ -0,0 +1,53 @@ +{ + "class": "Cloud_Failover", + "environment": "aws", + "controls": { + "class": "Controls", + "logLevel": "silly" + }, + "externalStorage": { + "scopingName": "myCloudFailoverBucket", + "encryption": { + "serverSide": { + "enabled": true, + "algorithm": "aws:kms" + } + } + }, + "failoverAddresses": { + "enabled": true, + "scopingTags": { + "f5_cloud_failover_label": "mydeployment" + }, + "addressGroupDefinitions": [ + { + "type": "networkInterfaceAddress", + "scopingAddress": "10.0.12.101" + }, + { + "type": "networkInterfaceAddress", + "scopingAddress": "10.0.12.102" + } + ] + }, + "failoverRoutes": { + "enabled": true, + "routeGroupDefinitions": [ + { + "scopingName": "rtb-11111111111111111", + "scopingAddressRanges": [ + { + "range": "0.0.0.0/0" + } + ], + "defaultNextHopAddresses": { + "discoveryType": "static", + "items": [ + "10.0.13.11", + "10.0.13.12" + ] + } + } + ] + } + } \ No newline at end of file From 57d80ae35df5da7af5d9351f581ec67e8edaedba Mon Sep 17 00:00:00 2001 From: Alex Applebaum Date: Tue, 13 Sep 2022 12:09:01 -0700 Subject: [PATCH 4/7] Updated Docs and examples to include SSE-S3 encyrption --- docs/userguide/aws-same-az.rst | 12 +++++++----- docs/userguide/aws.rst | 14 +++++++++----- examples/declarations/aws-across-az-1.13.0.json | 2 +- examples/declarations/aws-same-az-1.13.0.json | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/docs/userguide/aws-same-az.rst b/docs/userguide/aws-same-az.rst index 1fc344a0..8c37ae53 100644 --- a/docs/userguide/aws-same-az.rst +++ b/docs/userguide/aws-same-az.rst @@ -361,6 +361,9 @@ NOTE: If a customer managed KMS Encryption Key is used for server-side encryptio | +To limit encryption to a specific type or for more information, see `AWS Documentation `_. + + Alternatively, for *Actions* that **do** allow resource level permissions, but the specific resource IDs may not be known ahead of time, you can leverage *Condition* statements that limit access to only those resources with a certain tag. For example, in some orchestration workflows, the IAM instance profile and policy are created first in order to apply to the instance at creation time, but of course the instance IDs for the policy are not known yet. Instead, in the snippet below, *Conditions* are used so only resources with the ``f5_cloud_failover_label`` tag can be updated. .. code-block:: json @@ -463,8 +466,7 @@ Define the Storage Account in AWS .. sidebar:: :fonticon:`fa fa-info-circle fa-lg` Version Notice: - The property ``scopingName`` is available in Cloud Failover Extension v1.7.0 and later. - - Beginning v1.13.0, CFE supports Serverside Encryption on the S3 Bucket using AWS KMS (SSE-KMS) with either the default AWS managed key or a customer managed key. See `AWS Documentation `_ for more details on how to enable server-side encryption on the S3 bucket. - + - Beginning v1.13.0, CFE supports Serverside Encryption on the S3 Bucket using Amazon S3-Managed Keys (SSE-S3) or KMS keys Stored in AWS Key Management Service (SSE-KMS) with either the default AWS managed key or a customer managed key. See `AWS Documentation `_ for more details on how to enable server-side encryption on the S3 bucket. 1. Create an `S3 bucket in AWS `_ for Cloud Failover Extension cluster-wide file(s). @@ -481,12 +483,12 @@ Define the Storage Account in AWS "encryption": { "serverSide": { "enabled": true, - "algorithm": "aws:kms" + "algorithm": "AES256" } } }, - You can also optionally update/modify the serverside encyption config. See Click `here `_ to see an example using a customer managed key. + You can also optionally update/modify the serverside encyption config. The example above uses S3-Managed Keys (SSE-S3). To use KMS, set the ``algorithm`` attribute to "aws::kms". Click `here `_ to see an example using KMS and the default AWS managed key. Click `here `_ to see an example using KMS and a customer managed key. Alternatively, if you are using the Discovery via Tag option, tag the S3 bucket with your custom key:values in the `externalStorage.scopingTags` section of the CFE declaration. @@ -500,7 +502,7 @@ Define the Storage Account in AWS "encryption": { "serverSide": { "enabled": true, - "algorithm": "aws:kms" + "algorithm": "AES256" } } }, diff --git a/docs/userguide/aws.rst b/docs/userguide/aws.rst index 6822cbfd..37dfd7e4 100644 --- a/docs/userguide/aws.rst +++ b/docs/userguide/aws.rst @@ -352,6 +352,9 @@ NOTE: If a customer managed KMS Encryption Key is used for server-side encryptio | +To limit encryption to a specific type or for more information, see `AWS Documentation `_. + + Alternatively, for *Actions* that **do** allow resource level permissions, but the specific resource IDs may not be known ahead of time, you can leverage *Condition* statements that limit access to only those resources with a certain tag. For example, in some orchestration workflows, the IAM instance profile and policy are created first in order to apply to the instance at creation time, but the of course the instance IDs for the policy are not known yet. Instead, in the snippet below, *Conditions* are used so only resources with the `f5_cloud_failover_label` tag can be updated. .. code-block:: json @@ -442,7 +445,7 @@ Define the Storage Account in AWS .. sidebar:: :fonticon:`fa fa-info-circle fa-lg` Version Notice: - The property ``scopingName`` is available in Cloud Failover Extension v1.7.0 and later. - - Beginning v1.13.0, CFE supports Serverside Encryption on the S3 Bucket using AWS KMS (SSE-KMS) with either the default AWS managed key or a customer managed key. See `AWS Documentation `_ for more details on how to enable server-side encryption on the S3 bucket. + - Beginning v1.13.0, CFE supports Serverside Encryption on the S3 Bucket using Amazon S3-Managed Keys (SSE-S3) or KMS keys Stored in AWS Key Management Service (SSE-KMS) with either the default AWS managed key or a customer managed key. See `AWS Documentation `_ for more details on how to enable server-side encryption on the S3 bucket. @@ -451,7 +454,7 @@ Define the Storage Account in AWS .. WARNING:: To avoid a potential data breach, ensure the required S3 buckets are properly secured and do not have public access. See your cloud provider for best practices. -2. Update/modify the Cloud Failover ``scopingName`` value with name of your S3 bucket: +2. Update/modify the Cloud Failover ``scopingName`` value with **name** of your S3 bucket: .. code-block:: json :emphasize-lines: 2 @@ -461,12 +464,13 @@ Define the Storage Account in AWS "encryption": { "serverSide": { "enabled": true, - "algorithm": "aws:kms" + "algorithm": "AES256" } } }, - You can also optionally update/modify the serverside encyption config. See Click `here `_ to see an example using a customer managed key. + You can also optionally update/modify the serverside encyption config. The example above uses S3-Managed Keys (SSE-S3). To use KMS, set the ``algorithm`` attribute to "aws::kms". Click `here `_ to see an example using KMS and the default AWS managed key. Click `here `_ to see an example using KMS and a customer managed key. + Alternatively, if you are using the Discovery via Tag option, tag the S3 bucket with your custom key:values in the `externalStorage.scopingTags` section of the CFE declaration. @@ -480,7 +484,7 @@ Define the Storage Account in AWS "encryption": { "serverSide": { "enabled": true, - "algorithm": "aws:kms" + "algorithm": "AES256" } } }, diff --git a/examples/declarations/aws-across-az-1.13.0.json b/examples/declarations/aws-across-az-1.13.0.json index 3d6dafe2..6b2b7366 100644 --- a/examples/declarations/aws-across-az-1.13.0.json +++ b/examples/declarations/aws-across-az-1.13.0.json @@ -15,7 +15,7 @@ "encryption": { "serverSide": { "enabled": true, - "algorithm": "aws:kms" + "algorithm": "AES256" } } }, diff --git a/examples/declarations/aws-same-az-1.13.0.json b/examples/declarations/aws-same-az-1.13.0.json index 35409f67..327253c4 100644 --- a/examples/declarations/aws-same-az-1.13.0.json +++ b/examples/declarations/aws-same-az-1.13.0.json @@ -10,7 +10,7 @@ "encryption": { "serverSide": { "enabled": true, - "algorithm": "aws:kms" + "algorithm": "AES256" } } }, From 3c2664c6c669e045056f688dd3fb459fdd6b962b Mon Sep 17 00:00:00 2001 From: Alex Applebaum Date: Tue, 13 Sep 2022 12:29:12 -0700 Subject: [PATCH 5/7] typo in example declaration for across az --- examples/declarations/aws-across-az-1.13.0.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/declarations/aws-across-az-1.13.0.json b/examples/declarations/aws-across-az-1.13.0.json index 6b2b7366..55975d87 100644 --- a/examples/declarations/aws-across-az-1.13.0.json +++ b/examples/declarations/aws-across-az-1.13.0.json @@ -6,18 +6,18 @@ "logLevel": "silly" }, "externalStorage": { - "scopingName": "myCloudFailoverBucket" + "scopingName": "myCloudFailoverBucket", + "encryption": { + "serverSide": { + "enabled": true, + "algorithm": "AES256" + } + } }, "failoverAddresses": { "enabled": true, "scopingTags": { - "f5_cloud_failover_label": "mydeployment", - "encryption": { - "serverSide": { - "enabled": true, - "algorithm": "AES256" - } - } + "f5_cloud_failover_label": "mydeployment" }, "addressGroupDefinitions": [ { From 86b73b459d3f2843365317725ffd5241bf347aa8 Mon Sep 17 00:00:00 2001 From: Alex Applebaum Date: Tue, 13 Sep 2022 13:28:56 -0700 Subject: [PATCH 6/7] added KMS abbrev in aws.rst and aws-same-az.rst --- docs/userguide/aws-same-az.rst | 2 +- docs/userguide/aws.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/userguide/aws-same-az.rst b/docs/userguide/aws-same-az.rst index 8c37ae53..8960629f 100644 --- a/docs/userguide/aws-same-az.rst +++ b/docs/userguide/aws-same-az.rst @@ -488,7 +488,7 @@ Define the Storage Account in AWS } }, - You can also optionally update/modify the serverside encyption config. The example above uses S3-Managed Keys (SSE-S3). To use KMS, set the ``algorithm`` attribute to "aws::kms". Click `here `_ to see an example using KMS and the default AWS managed key. Click `here `_ to see an example using KMS and a customer managed key. + You can also optionally update/modify the serverside encyption config. The example above uses S3-Managed Keys (SSE-S3). To use KMS (SSE-KMS), set the ``algorithm`` attribute to "aws::kms". Click `here `_ to see an example using KMS and the default AWS managed key. Click `here `_ to see an example using KMS and a customer managed key. Alternatively, if you are using the Discovery via Tag option, tag the S3 bucket with your custom key:values in the `externalStorage.scopingTags` section of the CFE declaration. diff --git a/docs/userguide/aws.rst b/docs/userguide/aws.rst index 37dfd7e4..9cbbbf3e 100644 --- a/docs/userguide/aws.rst +++ b/docs/userguide/aws.rst @@ -469,7 +469,7 @@ Define the Storage Account in AWS } }, - You can also optionally update/modify the serverside encyption config. The example above uses S3-Managed Keys (SSE-S3). To use KMS, set the ``algorithm`` attribute to "aws::kms". Click `here `_ to see an example using KMS and the default AWS managed key. Click `here `_ to see an example using KMS and a customer managed key. + You can also optionally update/modify the serverside encyption config. The example above uses S3-Managed Keys (SSE-S3). To use KMS (SSE-KMS), set the ``algorithm`` attribute to "aws::kms". Click `here `_ to see an example using KMS and the default AWS managed key. Click `here `_ to see an example using KMS and a customer managed key. Alternatively, if you are using the Discovery via Tag option, tag the S3 bucket with your custom key:values in the `externalStorage.scopingTags` section of the CFE declaration. From 885bc676bfde4be03a45538210e8ca58f3bd517d Mon Sep 17 00:00:00 2001 From: Alex Applebaum Date: Tue, 13 Sep 2022 13:50:50 -0700 Subject: [PATCH 7/7] fixed format in aws.rst --- docs/userguide/aws.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/userguide/aws.rst b/docs/userguide/aws.rst index 9cbbbf3e..59c55512 100644 --- a/docs/userguide/aws.rst +++ b/docs/userguide/aws.rst @@ -469,8 +469,7 @@ Define the Storage Account in AWS } }, - You can also optionally update/modify the serverside encyption config. The example above uses S3-Managed Keys (SSE-S3). To use KMS (SSE-KMS), set the ``algorithm`` attribute to "aws::kms". Click `here `_ to see an example using KMS and the default AWS managed key. Click `here `_ to see an example using KMS and a customer managed key. - + You can also optionally update/modify the serverside encyption config. The example above uses S3-Managed Keys (SSE-S3). To use KMS (SSE-KMS), set the ``algorithm`` attribute to "aws::kms". Click `here `_ to see an example using KMS and the default AWS managed key. Click `here `_ to see an example using KMS and a customer managed key. Alternatively, if you are using the Discovery via Tag option, tag the S3 bucket with your custom key:values in the `externalStorage.scopingTags` section of the CFE declaration.