Repository: kubernetes-sigs/aws-alb-ingress-controller
Pull request #1126 (2020-01-13 07:20:42)

Add support for enabling AWS Shield Advanced protection
When subscribed to AWS Shield Advanced service, the Shield protection must be turned on for each Application Load Balancer resource. While AWS offers automation to do this via services like Firewall Manager, their use cases are limited by their constraints (e.g., impossible to utilize rate-based WAF rules [1]).

The proposed change adds an annotation for the ingress resource, which can is used to turn on the Shield Advanced protection for the load balancers created by aws-alb-ingress-controller. 

[1]: https://docs.aws.amazon.com/waf/latest/developerguide/ddos-get-started-rate-based-rules.html

k8s-ci-robot: Hi @hhamalai. Thanks for your PR.

I'm waiting for a [kubernetes-sigs](https://github.com/orgs/kubernetes-sigs/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://git.k8s.io/community/community-membership.md#member) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Faws-alb-ingress-controller).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

k8s-ci-robot: Welcome @hhamalai! <br><br>It looks like this is your first PR to <a href='https://github.com/kubernetes-sigs/aws-alb-ingress-controller'>kubernetes-sigs/aws-alb-ingress-controller</a> 🎉. Please refer to our [pull request process documentation](https://git.k8s.io/community/contributors/guide/pull-requests.md) to help your PR have a smooth ride to approval. <br><br>You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. [Here is the bot commands documentation](https://go.k8s.io/bot-commands). <br><br>You can also check if kubernetes-sigs/aws-alb-ingress-controller has [its own contribution guidelines](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/tree/master/CONTRIBUTING.md). <br><br>You may want to refer to our [testing guide](https://git.k8s.io/community/contributors/devel/sig-testing/testing.md) if you run into trouble with your tests not passing. <br><br>If you are having difficulty getting your pull request seen, please follow the [recommended escalation practices](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#why-is-my-pull-request-not-getting-reviewed). Also, for tips and tricks in the contribution process you may want to read the [Kubernetes contributor cheat sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet/README.md). We want to make sure your contribution gets all the attention it needs! <br><br>Thank you, and welcome to Kubernetes. :smiley:
k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/aws-alb-ingress-controller/pull/1126#" title="Author self-approved">hhamalai</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **bigkraig**
You can assign the PR to them by writing `/assign @bigkraig` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Faws-alb-ingress-controller).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["bigkraig"]} -->
alejandrox1: /ok-to-test
k8s-ci-robot: @hhamalai: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-unit-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1216750222219153408) | `/test pull-aws-alb-ingress-controller-unit-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-unit-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1216750222214959105) | `/test pull-aws-alb-ingress-controller-unit-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-unit-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1216750222214959105) | `/test pull-aws-alb-ingress-controller-unit-test`
pull-aws-alb-ingress-controller-e2e-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1216750222214959107) | `/test pull-aws-alb-ingress-controller-e2e-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-unit-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1216750222214959105) | `/test pull-aws-alb-ingress-controller-unit-test`
pull-aws-alb-ingress-controller-e2e-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1216750222219153409) | `/test pull-aws-alb-ingress-controller-e2e-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
M00nF1sh: Wow, thanks so much for contributing! 
/ok-to-test
k8s-ci-robot: @hhamalai: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-e2e-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1216750222219153409) | `/test pull-aws-alb-ingress-controller-e2e-test`
pull-aws-alb-ingress-controller-unit-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1216842097441640449) | `/test pull-aws-alb-ingress-controller-unit-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-unit-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1216842097441640449) | `/test pull-aws-alb-ingress-controller-unit-test`
pull-aws-alb-ingress-controller-e2e-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1216842097441640448) | `/test pull-aws-alb-ingress-controller-e2e-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: PR needs rebase.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
k8s-ci-robot: @hhamalai: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-unit-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1216842097441640449) | `/test pull-aws-alb-ingress-controller-unit-test`
pull-aws-alb-ingress-controller-e2e-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1216842097441640448) | `/test pull-aws-alb-ingress-controller-e2e-test`
pull-aws-alb-ingress-controller-lint | 11f32bae9dec722e6dd295468dee2a7fcee125b0 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-lint/1217006809940758530) | `/test pull-aws-alb-ingress-controller-lint`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-unit-test | 515a43311e60c55482fb3f872d04c32121b2d9db | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1216842097441640449) | `/test pull-aws-alb-ingress-controller-unit-test`
pull-aws-alb-ingress-controller-lint | 11f32bae9dec722e6dd295468dee2a7fcee125b0 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-lint/1217006809940758530) | `/test pull-aws-alb-ingress-controller-lint`
pull-aws-alb-ingress-controller-e2e-test | 11f32bae9dec722e6dd295468dee2a7fcee125b0 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1217006809940758533) | `/test pull-aws-alb-ingress-controller-e2e-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-lint | 11f32bae9dec722e6dd295468dee2a7fcee125b0 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-lint/1217006809940758530) | `/test pull-aws-alb-ingress-controller-lint`
pull-aws-alb-ingress-controller-e2e-test | 11f32bae9dec722e6dd295468dee2a7fcee125b0 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1217006809940758533) | `/test pull-aws-alb-ingress-controller-e2e-test`
pull-aws-alb-ingress-controller-unit-test | 11f32bae9dec722e6dd295468dee2a7fcee125b0 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1217006809940758531) | `/test pull-aws-alb-ingress-controller-unit-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-lint | 11f32bae9dec722e6dd295468dee2a7fcee125b0 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-lint/1217006809940758530) | `/test pull-aws-alb-ingress-controller-lint`
pull-aws-alb-ingress-controller-e2e-test | 11f32bae9dec722e6dd295468dee2a7fcee125b0 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1217006809940758533) | `/test pull-aws-alb-ingress-controller-e2e-test`
pull-aws-alb-ingress-controller-unit-test | 351012aafbebf064713ec41eea07825af76236b1 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1217100933981278208) | `/test pull-aws-alb-ingress-controller-unit-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-e2e-test | 11f32bae9dec722e6dd295468dee2a7fcee125b0 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1217006809940758533) | `/test pull-aws-alb-ingress-controller-e2e-test`
pull-aws-alb-ingress-controller-lint | 0b8520c45bf3fdb47848d09bca640210e5246201 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-lint/1217103449435410432) | `/test pull-aws-alb-ingress-controller-lint`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-e2e-test | 42346bbb2b846ce9381241af21256b634e9ffdaf | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1217108485305536512) | `/test pull-aws-alb-ingress-controller-e2e-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-e2e-test | 5b5376ba390addd08d1d98f6f0d6c901d42dcb4c | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1217154793844248578) | `/test pull-aws-alb-ingress-controller-e2e-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
hhamalai: /retest
hhamalai: /test pull-aws-alb-ingress-controller-e2e-test
k8s-ci-robot: @hhamalai: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-e2e-test | 5b5376ba390addd08d1d98f6f0d6c901d42dcb4c | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-e2e-test/1217154793844248578) | `/test pull-aws-alb-ingress-controller-e2e-test`
pull-aws-alb-ingress-controller-unit-test | 7132f35760bbd605d3bfc38a5e3e9017fbbed2fb | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1217217347157233665) | `/test pull-aws-alb-ingress-controller-unit-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
hhamalai: /assign @bigkraig
k8s-ci-robot: @hhamalai: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-lint | 0ab440d49a0a2c4b979dc0633e0bad9649e2b781 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-lint/1219333993707606017) | `/test pull-aws-alb-ingress-controller-lint`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-lint | cab384953b4c9a95078299eb039a41dfd89235fd | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-lint/1219342927000506370) | `/test pull-aws-alb-ingress-controller-lint`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
hhamalai: Hi, can @bigkraig give any feedback how to take this proposed change further? Should try to drag more review feedback or assign this into some person to review?
M00nF1sh: I'll test this out today
M00nF1sh: /lgtm
/approve
k8s-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/aws-alb-ingress-controller/pull/1126#" title="Author self-approved">hhamalai</a>*, *<a href="https://github.com/kubernetes-sigs/aws-alb-ingress-controller/pull/1126#issuecomment-578877312" title="Approved">M00nF1sh</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Faws-alb-ingress-controller).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/blob/master/OWNERS)~~ [M00nF1sh]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
hhamalai: Thanks for the great feedback, I'm happy to implement your suggestions and ping you once ready. 
k8s-ci-robot: New changes are detected. LGTM label has been removed.
k8s-ci-robot: @hhamalai: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-lint | b8a68ea96a2b384a76fc5e277c62e92011047af1 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-lint/1222421799174672386) | `/test pull-aws-alb-ingress-controller-lint`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @hhamalai: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-aws-alb-ingress-controller-unit-test | 73d2c4251496796c4126e44136dde83142f867fb | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-alb-ingress-controller/1126/pull-aws-alb-ingress-controller-unit-test/1222535148596105218) | `/test pull-aws-alb-ingress-controller-unit-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-alb-ingress-controller&pr=1126). [Your PR dashboard](https://gubernator.k8s.io/pr/hhamalai). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-alb-ingress-controller/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/docs/examples/iam-policy.json b/docs/examples/iam-policy.json
index 41bd2a08e..0d8d3461a 100644
--- a/docs/examples/iam-policy.json
+++ b/docs/examples/iam-policy.json
@@ -113,6 +113,18 @@
         "waf:GetWebACL"
       ],
       "Resource": "*"
+    },
+    {
+      "Effect": "Allow",
+      "Action": [
+        "shield:DescribeProtection",
+        "shield:GetSubscriptionState",
+        "shield:DeleteProtection",
+        "shield:CreateProtection",
+        "shield:DescribeSubscription",
+        "shield:ListProtections"
+      ],
+      "Resource": "*"
     }
   ]
 }
diff --git a/docs/guide/ingress/annotation.md b/docs/guide/ingress/annotation.md
index 7e80c6095..e184a756d 100644
--- a/docs/guide/ingress/annotation.md
+++ b/docs/guide/ingress/annotation.md
@@ -4,6 +4,7 @@ You can add kubernetes annotations to ingress and service objects to customize t
 !!!note
     - Annotations applied to service have higher priority over annotations applied to ingress. `Location` column below indicates where that annotation can be applied to.
     - Annotation keys and values can only be strings. Advanced format are encoded as below:
+        - boolean: 'true'
         - integer: '42'
         - stringMap: k1=v1,k2=v2
         - stringList: s1,s2,s3
@@ -37,6 +38,7 @@ You can add kubernetes annotations to ingress and service objects to customize t
 |[alb.ingress.kubernetes.io/load-balancer-attributes](#load-balancer-attributes)|stringMap|N/A|ingress|
 |[alb.ingress.kubernetes.io/scheme](#scheme)|internal \| internet-facing|internal|ingress|
 |[alb.ingress.kubernetes.io/security-groups](#security-groups)|stringList|N/A|ingress|
+|[alb.ingress.kubernetes.io/shield-advanced-protection](#shield-advanced-protection)|boolean|N/A|ingress|
 |[alb.ingress.kubernetes.io/ssl-policy](#ssl-policy)|string|ELBSecurityPolicy-2016-08|ingress|
 |[alb.ingress.kubernetes.io/subnets](#subnets)|stringList|N/A|ingress|
 |[alb.ingress.kubernetes.io/success-codes](#success-codes)|string|'200'|ingress,service|
@@ -488,6 +490,13 @@ Health check on target groups can be controlled with following annotations:
         ```alb.ingress.kubernetes.io/waf-acl-id: 499e8b99-6671-4614-a86d-adb1810b7fbe
         ```
 
+## Shield Advanced
+- <a name="shield-advanced-protection">`alb.ingress.kubernetes.io/shield-advanced-protection`</a> turns on / off the AWS Shield Advanced protection for the load balancer.
+
+    !!!example
+        ```alb.ingress.kubernetes.io/shield-advanced-protection: 'true'
+        ```
+
 ## SSL
 SSL support can be controlled with following annotations:
 
diff --git a/internal/alb/lb/loadbalancer.go b/internal/alb/lb/loadbalancer.go
index 148d8632b..d807ebef3 100644
--- a/internal/alb/lb/loadbalancer.go
+++ b/internal/alb/lb/loadbalancer.go
@@ -46,6 +46,7 @@ func NewController(
 	tagsController tags.Controller) Controller {
 	attrsController := NewAttributesController(cloud)
 	wafController := NewWAFController(cloud)
+	shieldController := NewShieldController(cloud)
 
 	return &defaultController{
 		cloud:                   cloud,
@@ -57,6 +58,7 @@ func NewController(
 		tagsController:          tagsController,
 		attrsController:         attrsController,
 		wafController:           wafController,
+		shieldController:        shieldController,
 	}
 }
 
@@ -81,6 +83,7 @@ type defaultController struct {
 	tagsController          tags.Controller
 	attrsController         AttributesController
 	wafController           WAFController
+	shieldController        ShieldController
 }
 
 var _ Controller = (*defaultController)(nil)
@@ -119,6 +122,12 @@ func (controller *defaultController) Reconcile(ctx context.Context, ingress *ext
 		}
 	}
 
+	if controller.store.GetConfig().FeatureGate.Enabled(config.ShieldAdvanced) {
+		if err := controller.shieldController.Reconcile(ctx, lbArn, ingress); err != nil {
+			return nil, err
+		}
+	}
+
 	tgGroup, err := controller.tgGroupController.Reconcile(ctx, ingress)
 	if err != nil {
 		return nil, fmt.Errorf("failed to reconcile targetGroups due to %v", err)
diff --git a/internal/alb/lb/shield.go b/internal/alb/lb/shield.go
new file mode 100644
index 000000000..1237dcc0c
--- /dev/null
+++ b/internal/alb/lb/shield.go
@@ -0,0 +1,129 @@
+package lb
+
+import (
+	"context"
+	"fmt"
+	"strconv"
+	"time"
+
+	"github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/ingress/annotations"
+
+	"github.com/aws/aws-sdk-go/service/shield"
+	"github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/albctx"
+	"github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/aws"
+	"github.com/pkg/errors"
+	extensions "k8s.io/api/extensions/v1beta1"
+
+	"k8s.io/apimachinery/pkg/util/cache"
+)
+
+const (
+	protectionEnabledForLBCacheMaxSize = 1024
+	protectionEnabledForLBCacheTTL     = 10 * time.Second
+	shieldAvailableCacheMaxSize        = 1
+	shieldAvailableCacheTTL            = 10 * time.Second
+	shieldAvailableCacheKey            = "shieldAvailable"
+	protectionName                     = "managed by aws-alb-ingress-controller"
+)
+
+// ShieldController provides functionality to manage ALB's Shield Advanced protection.
+type ShieldController interface {
+	Reconcile(ctx context.Context, lbArn string, ingress *extensions.Ingress) error
+}
+
+func NewShieldController(cloud aws.CloudAPI) ShieldController {
+	return &defaultShieldController{
+		cloud:                       cloud,
+		protectionEnabledForLBCache: cache.NewLRUExpireCache(protectionEnabledForLBCacheMaxSize),
+		shieldAvailableCache:        cache.NewLRUExpireCache(shieldAvailableCacheMaxSize),
+	}
+}
+
+type defaultShieldController struct {
+	cloud aws.CloudAPI
+
+	// cache that stores protection id for LoadBalancerARN.
+	// The cache value is string, while "" represents no protection.
+	protectionEnabledForLBCache *cache.LRUExpireCache
+	// cache that stores shield availability for current account.
+	// The cache value is string, while "" represents not available.
+	shieldAvailableCache *cache.LRUExpireCache
+}
+
+func (c *defaultShieldController) Reconcile(ctx context.Context, lbArn string, ingress *extensions.Ingress) error {
+	var enableProtection bool
+	annotationPresent, err := annotations.LoadBoolAnnocation("shield-advanced-protection", &enableProtection, ingress.Annotations)
+	if err != nil {
+		return err
+	}
+	if !annotationPresent {
+		return nil
+	}
+
+	available, err := c.getCurrentShieldAvailability(ctx)
+	if err != nil {
+		return err
+	}
+
+	if enableProtection && !available {
+		return fmt.Errorf("unable to create shield advanced protection for loadBalancer %v, shield advanced subscription is not active", lbArn)
+	}
+
+	protection, err := c.getCurrentProtectionStatus(ctx, lbArn)
+	if err != nil {
+		return fmt.Errorf("failed to get shield advanced protection status for loadBalancer %v due to %v", lbArn, err)
+	}
+
+	if protection == nil && enableProtection {
+		_, err := c.cloud.CreateProtection(ctx, aws.String(lbArn), aws.String(protectionName))
+		if err != nil {
+			return fmt.Errorf("failed to create shield advanced protection for loadBalancer %v due to %v", lbArn, err)
+		}
+		albctx.GetLogger(ctx).Infof("enabled shield advanced protection for %v", lbArn)
+	} else if protection != nil && !enableProtection {
+		if aws.StringValue(protection.Name) == protectionName {
+			_, err := c.cloud.DeleteProtection(ctx, protection.Id)
+			c.protectionEnabledForLBCache.Remove(lbArn)
+			if err != nil {
+				return fmt.Errorf("failed to delete shield advanced protection for loadBalancer %v due to %v", lbArn, err)
+			}
+
+			albctx.GetLogger(ctx).Infof("deleted shield advanced protection for %v", lbArn)
+		} else {
+			albctx.GetLogger(ctx).Warnf("unable to delete shield advanced protection for %v, the protection name does not match \"%v\"", lbArn, protectionName)
+		}
+	}
+	return nil
+}
+
+func (c *defaultShieldController) getCurrentShieldAvailability(ctx context.Context) (bool, error) {
+	cachedShieldAvailable, exists := c.shieldAvailableCache.Get(shieldAvailableCacheKey)
+	if exists {
+		available, err := strconv.ParseBool(cachedShieldAvailable.(string))
+		if err == nil {
+			return available, nil
+		}
+	}
+
+	available, err := c.cloud.ShieldAvailable(ctx)
+	if err != nil {
+		return false, fmt.Errorf("failed to get shield advanced subscription state %v", err)
+	}
+	c.shieldAvailableCache.Add(shieldAvailableCacheKey, "true", shieldAvailableCacheTTL)
+	return available, nil
+}
+
+func (c *defaultShieldController) getCurrentProtectionStatus(ctx context.Context, lbArn string) (*shield.Protection, error) {
+	cachedProtection, exists := c.protectionEnabledForLBCache.Get(lbArn)
+	if exists {
+		return cachedProtection.(*shield.Protection), nil
+	}
+
+	protection, err := c.cloud.GetProtection(ctx, aws.String(lbArn))
+	if err != nil {
+		return nil, errors.Wrapf(err, "failed to get protection status for load balancer %v", lbArn)
+	}
+
+	c.protectionEnabledForLBCache.Add(lbArn, protection, protectionEnabledForLBCacheTTL)
+	return protection, nil
+}
diff --git a/internal/aws/cloud.go b/internal/aws/cloud.go
index 943a2f9db..3fb447966 100644
--- a/internal/aws/cloud.go
+++ b/internal/aws/cloud.go
@@ -15,6 +15,8 @@ import (
 	"github.com/aws/aws-sdk-go/service/iam/iamiface"
 	"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
 	"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/resourcegroupstaggingapiiface"
+	"github.com/aws/aws-sdk-go/service/shield"
+	"github.com/aws/aws-sdk-go/service/shield/shieldiface"
 	"github.com/aws/aws-sdk-go/service/wafregional"
 	"github.com/aws/aws-sdk-go/service/wafregional/wafregionaliface"
 	"github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/ingress/metric"
@@ -26,6 +28,7 @@ type CloudAPI interface {
 	ELBV2API
 	IAMAPI
 	ResourceGroupsTaggingAPIAPI
+	ShieldAPI
 	WAFRegionalAPI
 
 	GetClusterName() string
@@ -41,6 +44,7 @@ type Cloud struct {
 	ec2         ec2iface.EC2API
 	elbv2       elbv2iface.ELBV2API
 	iam         iamiface.IAMAPI
+	shield      shieldiface.ShieldAPI
 	rgt         resourcegroupstaggingapiiface.ResourceGroupsTaggingAPIAPI
 	wafregional wafregionaliface.WAFRegionalAPI
 }
@@ -77,6 +81,7 @@ func New(cfg CloudConfig, clusterName string, mc metric.Collector) (CloudAPI, er
 		ec2.New(awsSession, regionCfg),
 		elbv2.New(awsSession, regionCfg),
 		iam.New(awsSession, regionCfg),
+		shield.New(awsSession, &aws.Config{Region: aws.String("us-east-1")}),
 		resourcegroupstaggingapi.New(awsSession, regionCfg),
 		wafregional.New(awsSession, regionCfg),
 	}, nil
diff --git a/internal/aws/shield.go b/internal/aws/shield.go
new file mode 100644
index 000000000..793661921
--- /dev/null
+++ b/internal/aws/shield.go
@@ -0,0 +1,57 @@
+package aws
+
+import (
+	"context"
+
+	"github.com/aws/aws-sdk-go/aws/awserr"
+	"github.com/aws/aws-sdk-go/service/shield"
+)
+
+type ShieldAPI interface {
+	ShieldAvailable(ctx context.Context) (bool, error)
+	GetSubscriptionStatus(ctx context.Context) (*shield.GetSubscriptionStateOutput, error)
+	GetProtection(ctx context.Context, resourceArn *string) (*shield.Protection, error)
+	CreateProtection(ctx context.Context, resourceArn *string, protectionName *string) (*shield.CreateProtectionOutput, error)
+	DeleteProtection(ctx context.Context, protectionID *string) (*shield.DeleteProtectionOutput, error)
+}
+
+func (c *Cloud) ShieldAvailable(ctx context.Context) (bool, error) {
+	status, err := c.GetSubscriptionStatus(ctx)
+	if err != nil {
+		return false, err
+	}
+	return *status.SubscriptionState == "ACTIVE", nil
+}
+
+func (c *Cloud) GetSubscriptionStatus(ctx context.Context) (*shield.GetSubscriptionStateOutput, error) {
+	return c.shield.GetSubscriptionStateWithContext(ctx, &shield.GetSubscriptionStateInput{})
+}
+
+func (c *Cloud) GetProtection(ctx context.Context, resourceArn *string) (*shield.Protection, error) {
+	result, err := c.shield.DescribeProtectionWithContext(ctx, &shield.DescribeProtectionInput{
+		ResourceArn: resourceArn,
+	})
+
+	if err != nil {
+		aerr, ok := err.(awserr.Error)
+		if ok && aerr.Code() == shield.ErrCodeResourceNotFoundException {
+			return nil, nil
+		}
+		return nil, err
+	}
+
+	return result.Protection, nil
+}
+
+func (c *Cloud) CreateProtection(ctx context.Context, resourceArn *string, protectionName *string) (*shield.CreateProtectionOutput, error) {
+	return c.shield.CreateProtectionWithContext(ctx, &shield.CreateProtectionInput{
+		Name:        protectionName,
+		ResourceArn: resourceArn,
+	})
+}
+
+func (c *Cloud) DeleteProtection(ctx context.Context, protectionID *string) (*shield.DeleteProtectionOutput, error) {
+	return c.shield.DeleteProtectionWithContext(ctx, &shield.DeleteProtectionInput{
+		ProtectionId: protectionID,
+	})
+}
diff --git a/internal/ingress/annotations/annotations.go b/internal/ingress/annotations/annotations.go
index 2804ab5e7..cd9d177fd 100644
--- a/internal/ingress/annotations/annotations.go
+++ b/internal/ingress/annotations/annotations.go
@@ -200,6 +200,20 @@ func LoadStringSliceAnnotation(annotation string, value *[]string, annotations .
 	return true
 }
 
+func LoadBoolAnnocation(annotation string, value *bool, annotations ...map[string]string) (bool, error) {
+	key := parser.GetAnnotationWithPrefix(annotation)
+	raw, ok := utils.MapFindFirst(key, annotations...)
+	if !ok {
+		return false, nil
+	}
+	b, err := strconv.ParseBool(raw)
+	if err != nil {
+		return true, pkgerrors.Wrapf(err, "failed to parse annotation, %v: %v", key, raw)
+	}
+	*value = b
+	return true, nil
+}
+
 // LoadInt64Annotation loads annotation into value of type int64 from list of annotations by priority.
 func LoadInt64Annotation(annotation string, value *int64, annotations ...map[string]string) (bool, error) {
 	key := parser.GetAnnotationWithPrefix(annotation)
diff --git a/internal/ingress/annotations/loadbalancer/main.go b/internal/ingress/annotations/loadbalancer/main.go
index 084e9a067..f1187cf21 100644
--- a/internal/ingress/annotations/loadbalancer/main.go
+++ b/internal/ingress/annotations/loadbalancer/main.go
@@ -37,8 +37,10 @@ type PortData struct {
 }
 
 type Config struct {
-	Scheme        *string
-	IPAddressType *string
+	Scheme         *string
+	IPAddressType  *string
+	WebACLId       *string
+	ShieldAdvanced *bool
 
 	InboundCidrs   []string
 	InboundV6CIDRs []string
@@ -95,6 +97,11 @@ func (lb loadBalancer) Parse(ing parser.AnnotationInterface) (interface{}, error
 	securityGroups := parser.GetStringSliceAnnotation("security-groups", ing)
 	subnets := parser.GetStringSliceAnnotation("subnets", ing)
 
+	shieldAdvanced, err := parseBoolean(ing, aws.String("shield-advanced-protection"))
+	if err != nil {
+		return nil, err
+	}
+
 	v4CIDRs, v6CIDRs, err := parseCidrs(ing)
 	if err != nil {
 		return nil, err
@@ -108,12 +115,24 @@ func (lb loadBalancer) Parse(ing parser.AnnotationInterface) (interface{}, error
 		InboundCidrs:   v4CIDRs,
 		InboundV6CIDRs: v6CIDRs,
 		Ports:          ports,
+		ShieldAdvanced: shieldAdvanced,
 
 		Subnets:        subnets,
 		SecurityGroups: securityGroups,
 	}, nil
 }
 
+// parses boolean annotation and returns reference to it or nil if missing
+func parseBoolean(ing parser.AnnotationInterface, key *string) (*bool, error) {
+	value, err := parser.GetBoolAnnotation(aws.StringValue(key), ing)
+	if err == errors.ErrMissingAnnotations {
+		return nil, nil
+	} else if err != nil {
+		return nil, err
+	}
+	return value, nil
+}
+
 func parseAttributes(ing parser.AnnotationInterface) ([]*elbv2.LoadBalancerAttribute, error) {
 	var badAttrs []string
 	var lbattrs []*elbv2.LoadBalancerAttribute
diff --git a/internal/ingress/controller/config/features.go b/internal/ingress/controller/config/features.go
index d59377a05..27d44a829 100644
--- a/internal/ingress/controller/config/features.go
+++ b/internal/ingress/controller/config/features.go
@@ -27,7 +27,8 @@ import (
 type Feature string
 
 const (
-	WAF Feature = "waf"
+	WAF            Feature = "waf"
+	ShieldAdvanced Feature = "shield"
 )
 
 type FeatureGate interface {
@@ -55,7 +56,8 @@ type defaultFeatureGate struct {
 func NewFeatureGate() FeatureGate {
 	return &defaultFeatureGate{
 		featureState: map[Feature]bool{
-			WAF: true,
+			WAF:            true,
+			ShieldAdvanced: true,
 		},
 	}
 }
diff --git a/mocks/CloudAPI.go b/mocks/CloudAPI.go
index f1640e03b..9ddbdac11 100644
--- a/mocks/CloudAPI.go
+++ b/mocks/CloudAPI.go
@@ -15,6 +15,8 @@ import (
 
 	resourcegroupstaggingapi "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
 
+	shield "github.com/aws/aws-sdk-go/service/shield"
+
 	waf "github.com/aws/aws-sdk-go/service/waf"
 
 	wafregional "github.com/aws/aws-sdk-go/service/wafregional"
@@ -200,6 +202,29 @@ func (_m *CloudAPI) CreateLoadBalancerWithContext(_a0 context.Context, _a1 *elbv
 	return r0, r1
 }
 
+// CreateProtection provides a mock function with given fields: ctx, resourceArn, protectionName
+func (_m *CloudAPI) CreateProtection(ctx context.Context, resourceArn *string, protectionName *string) (*shield.CreateProtectionOutput, error) {
+	ret := _m.Called(ctx, resourceArn, protectionName)
+
+	var r0 *shield.CreateProtectionOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *string, *string) *shield.CreateProtectionOutput); ok {
+		r0 = rf(ctx, resourceArn, protectionName)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.CreateProtectionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *string, *string) error); ok {
+		r1 = rf(ctx, resourceArn, protectionName)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
 // CreateRuleWithContext provides a mock function with given fields: _a0, _a1
 func (_m *CloudAPI) CreateRuleWithContext(_a0 context.Context, _a1 *elbv2.CreateRuleInput) (*elbv2.CreateRuleOutput, error) {
 	ret := _m.Called(_a0, _a1)
@@ -320,6 +345,29 @@ func (_m *CloudAPI) DeleteLoadBalancerByArn(_a0 context.Context, _a1 string) err
 	return r0
 }
 
+// DeleteProtection provides a mock function with given fields: ctx, protectionID
+func (_m *CloudAPI) DeleteProtection(ctx context.Context, protectionID *string) (*shield.DeleteProtectionOutput, error) {
+	ret := _m.Called(ctx, protectionID)
+
+	var r0 *shield.DeleteProtectionOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *string) *shield.DeleteProtectionOutput); ok {
+		r0 = rf(ctx, protectionID)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DeleteProtectionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *string) error); ok {
+		r1 = rf(ctx, protectionID)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
 // DeleteRuleWithContext provides a mock function with given fields: _a0, _a1
 func (_m *CloudAPI) DeleteRuleWithContext(_a0 context.Context, _a1 *elbv2.DeleteRuleInput) (*elbv2.DeleteRuleOutput, error) {
 	ret := _m.Called(_a0, _a1)
@@ -615,9 +663,9 @@ func (_m *CloudAPI) GetClusterName() string {
 	return r0
 }
 
-// GetClusterSubnets provides a mock function with given fields:
+// GetClusterSubnets provides a mock function with given fields: _a0
 func (_m *CloudAPI) GetClusterSubnets(_a0 string) ([]*ec2.Subnet, error) {
-	ret := _m.Called()
+	ret := _m.Called(_a0)
 
 	var r0 []*ec2.Subnet
 	if rf, ok := ret.Get(0).(func(string) []*ec2.Subnet); ok {
@@ -707,6 +755,29 @@ func (_m *CloudAPI) GetLoadBalancerByName(_a0 context.Context, _a1 string) (*elb
 	return r0, r1
 }
 
+// GetProtection provides a mock function with given fields: ctx, resourceArn
+func (_m *CloudAPI) GetProtection(ctx context.Context, resourceArn *string) (*shield.Protection, error) {
+	ret := _m.Called(ctx, resourceArn)
+
+	var r0 *shield.Protection
+	if rf, ok := ret.Get(0).(func(context.Context, *string) *shield.Protection); ok {
+		r0 = rf(ctx, resourceArn)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.Protection)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *string) error); ok {
+		r1 = rf(ctx, resourceArn)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
 // GetResourcesByFilters provides a mock function with given fields: tagFilters, resourceTypeFilters
 func (_m *CloudAPI) GetResourcesByFilters(tagFilters map[string][]string, resourceTypeFilters ...string) ([]string, error) {
 	_va := make([]interface{}, len(resourceTypeFilters))
@@ -852,6 +923,29 @@ func (_m *CloudAPI) GetSubnetsByNameOrID(_a0 context.Context, _a1 []string) ([]*
 	return r0, r1
 }
 
+// GetSubscriptionStatus provides a mock function with given fields: ctx
+func (_m *CloudAPI) GetSubscriptionStatus(ctx context.Context) (*shield.GetSubscriptionStateOutput, error) {
+	ret := _m.Called(ctx)
+
+	var r0 *shield.GetSubscriptionStateOutput
+	if rf, ok := ret.Get(0).(func(context.Context) *shield.GetSubscriptionStateOutput); ok {
+		r0 = rf(ctx)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.GetSubscriptionStateOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+		r1 = rf(ctx)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
 // GetTargetGroupByArn provides a mock function with given fields: _a0, _a1
 func (_m *CloudAPI) GetTargetGroupByArn(_a0 context.Context, _a1 string) (*elbv2.TargetGroup, error) {
 	ret := _m.Called(_a0, _a1)
@@ -1324,6 +1418,27 @@ func (_m *CloudAPI) SetSubnetsWithContext(_a0 context.Context, _a1 *elbv2.SetSub
 	return r0, r1
 }
 
+// ShieldAvailable provides a mock function with given fields: ctx
+func (_m *CloudAPI) ShieldAvailable(ctx context.Context) (bool, error) {
+	ret := _m.Called(ctx)
+
+	var r0 bool
+	if rf, ok := ret.Get(0).(func(context.Context) bool); ok {
+		r0 = rf(ctx)
+	} else {
+		r0 = ret.Get(0).(bool)
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+		r1 = rf(ctx)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
 // StatusACM provides a mock function with given fields:
 func (_m *CloudAPI) StatusACM() func() error {
 	ret := _m.Called()
diff --git a/mocks/ShieldAPI.go b/mocks/ShieldAPI.go
new file mode 100644
index 000000000..5c55fd9bf
--- /dev/null
+++ b/mocks/ShieldAPI.go
@@ -0,0 +1,1421 @@
+// Code generated by mockery v1.0.0. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	request "github.com/aws/aws-sdk-go/aws/request"
+	mock "github.com/stretchr/testify/mock"
+
+	shield "github.com/aws/aws-sdk-go/service/shield"
+)
+
+// ShieldAPI is an autogenerated mock type for the ShieldAPI type
+type ShieldAPI struct {
+	mock.Mock
+}
+
+// AssociateDRTLogBucket provides a mock function with given fields: _a0
+func (_m *ShieldAPI) AssociateDRTLogBucket(_a0 *shield.AssociateDRTLogBucketInput) (*shield.AssociateDRTLogBucketOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.AssociateDRTLogBucketOutput
+	if rf, ok := ret.Get(0).(func(*shield.AssociateDRTLogBucketInput) *shield.AssociateDRTLogBucketOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.AssociateDRTLogBucketOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.AssociateDRTLogBucketInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// AssociateDRTLogBucketRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) AssociateDRTLogBucketRequest(_a0 *shield.AssociateDRTLogBucketInput) (*request.Request, *shield.AssociateDRTLogBucketOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.AssociateDRTLogBucketInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.AssociateDRTLogBucketOutput
+	if rf, ok := ret.Get(1).(func(*shield.AssociateDRTLogBucketInput) *shield.AssociateDRTLogBucketOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.AssociateDRTLogBucketOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// AssociateDRTLogBucketWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) AssociateDRTLogBucketWithContext(_a0 context.Context, _a1 *shield.AssociateDRTLogBucketInput, _a2 ...request.Option) (*shield.AssociateDRTLogBucketOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.AssociateDRTLogBucketOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.AssociateDRTLogBucketInput, ...request.Option) *shield.AssociateDRTLogBucketOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.AssociateDRTLogBucketOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.AssociateDRTLogBucketInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// AssociateDRTRole provides a mock function with given fields: _a0
+func (_m *ShieldAPI) AssociateDRTRole(_a0 *shield.AssociateDRTRoleInput) (*shield.AssociateDRTRoleOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.AssociateDRTRoleOutput
+	if rf, ok := ret.Get(0).(func(*shield.AssociateDRTRoleInput) *shield.AssociateDRTRoleOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.AssociateDRTRoleOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.AssociateDRTRoleInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// AssociateDRTRoleRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) AssociateDRTRoleRequest(_a0 *shield.AssociateDRTRoleInput) (*request.Request, *shield.AssociateDRTRoleOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.AssociateDRTRoleInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.AssociateDRTRoleOutput
+	if rf, ok := ret.Get(1).(func(*shield.AssociateDRTRoleInput) *shield.AssociateDRTRoleOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.AssociateDRTRoleOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// AssociateDRTRoleWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) AssociateDRTRoleWithContext(_a0 context.Context, _a1 *shield.AssociateDRTRoleInput, _a2 ...request.Option) (*shield.AssociateDRTRoleOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.AssociateDRTRoleOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.AssociateDRTRoleInput, ...request.Option) *shield.AssociateDRTRoleOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.AssociateDRTRoleOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.AssociateDRTRoleInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// CreateProtection provides a mock function with given fields: _a0
+func (_m *ShieldAPI) CreateProtection(_a0 *shield.CreateProtectionInput) (*shield.CreateProtectionOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.CreateProtectionOutput
+	if rf, ok := ret.Get(0).(func(*shield.CreateProtectionInput) *shield.CreateProtectionOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.CreateProtectionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.CreateProtectionInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// CreateProtectionRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) CreateProtectionRequest(_a0 *shield.CreateProtectionInput) (*request.Request, *shield.CreateProtectionOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.CreateProtectionInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.CreateProtectionOutput
+	if rf, ok := ret.Get(1).(func(*shield.CreateProtectionInput) *shield.CreateProtectionOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.CreateProtectionOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// CreateProtectionWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) CreateProtectionWithContext(_a0 context.Context, _a1 *shield.CreateProtectionInput, _a2 ...request.Option) (*shield.CreateProtectionOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.CreateProtectionOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.CreateProtectionInput, ...request.Option) *shield.CreateProtectionOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.CreateProtectionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.CreateProtectionInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// CreateSubscription provides a mock function with given fields: _a0
+func (_m *ShieldAPI) CreateSubscription(_a0 *shield.CreateSubscriptionInput) (*shield.CreateSubscriptionOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.CreateSubscriptionOutput
+	if rf, ok := ret.Get(0).(func(*shield.CreateSubscriptionInput) *shield.CreateSubscriptionOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.CreateSubscriptionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.CreateSubscriptionInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// CreateSubscriptionRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) CreateSubscriptionRequest(_a0 *shield.CreateSubscriptionInput) (*request.Request, *shield.CreateSubscriptionOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.CreateSubscriptionInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.CreateSubscriptionOutput
+	if rf, ok := ret.Get(1).(func(*shield.CreateSubscriptionInput) *shield.CreateSubscriptionOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.CreateSubscriptionOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// CreateSubscriptionWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) CreateSubscriptionWithContext(_a0 context.Context, _a1 *shield.CreateSubscriptionInput, _a2 ...request.Option) (*shield.CreateSubscriptionOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.CreateSubscriptionOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.CreateSubscriptionInput, ...request.Option) *shield.CreateSubscriptionOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.CreateSubscriptionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.CreateSubscriptionInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DeleteProtection provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DeleteProtection(_a0 *shield.DeleteProtectionInput) (*shield.DeleteProtectionOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.DeleteProtectionOutput
+	if rf, ok := ret.Get(0).(func(*shield.DeleteProtectionInput) *shield.DeleteProtectionOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DeleteProtectionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.DeleteProtectionInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DeleteProtectionRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DeleteProtectionRequest(_a0 *shield.DeleteProtectionInput) (*request.Request, *shield.DeleteProtectionOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.DeleteProtectionInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.DeleteProtectionOutput
+	if rf, ok := ret.Get(1).(func(*shield.DeleteProtectionInput) *shield.DeleteProtectionOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.DeleteProtectionOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// DeleteProtectionWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) DeleteProtectionWithContext(_a0 context.Context, _a1 *shield.DeleteProtectionInput, _a2 ...request.Option) (*shield.DeleteProtectionOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.DeleteProtectionOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.DeleteProtectionInput, ...request.Option) *shield.DeleteProtectionOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DeleteProtectionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.DeleteProtectionInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DeleteSubscription provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DeleteSubscription(_a0 *shield.DeleteSubscriptionInput) (*shield.DeleteSubscriptionOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.DeleteSubscriptionOutput
+	if rf, ok := ret.Get(0).(func(*shield.DeleteSubscriptionInput) *shield.DeleteSubscriptionOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DeleteSubscriptionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.DeleteSubscriptionInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DeleteSubscriptionRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DeleteSubscriptionRequest(_a0 *shield.DeleteSubscriptionInput) (*request.Request, *shield.DeleteSubscriptionOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.DeleteSubscriptionInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.DeleteSubscriptionOutput
+	if rf, ok := ret.Get(1).(func(*shield.DeleteSubscriptionInput) *shield.DeleteSubscriptionOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.DeleteSubscriptionOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// DeleteSubscriptionWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) DeleteSubscriptionWithContext(_a0 context.Context, _a1 *shield.DeleteSubscriptionInput, _a2 ...request.Option) (*shield.DeleteSubscriptionOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.DeleteSubscriptionOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.DeleteSubscriptionInput, ...request.Option) *shield.DeleteSubscriptionOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DeleteSubscriptionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.DeleteSubscriptionInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DescribeAttack provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DescribeAttack(_a0 *shield.DescribeAttackInput) (*shield.DescribeAttackOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.DescribeAttackOutput
+	if rf, ok := ret.Get(0).(func(*shield.DescribeAttackInput) *shield.DescribeAttackOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DescribeAttackOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.DescribeAttackInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DescribeAttackRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DescribeAttackRequest(_a0 *shield.DescribeAttackInput) (*request.Request, *shield.DescribeAttackOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.DescribeAttackInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.DescribeAttackOutput
+	if rf, ok := ret.Get(1).(func(*shield.DescribeAttackInput) *shield.DescribeAttackOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.DescribeAttackOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// DescribeAttackWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) DescribeAttackWithContext(_a0 context.Context, _a1 *shield.DescribeAttackInput, _a2 ...request.Option) (*shield.DescribeAttackOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.DescribeAttackOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.DescribeAttackInput, ...request.Option) *shield.DescribeAttackOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DescribeAttackOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.DescribeAttackInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DescribeDRTAccess provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DescribeDRTAccess(_a0 *shield.DescribeDRTAccessInput) (*shield.DescribeDRTAccessOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.DescribeDRTAccessOutput
+	if rf, ok := ret.Get(0).(func(*shield.DescribeDRTAccessInput) *shield.DescribeDRTAccessOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DescribeDRTAccessOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.DescribeDRTAccessInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DescribeDRTAccessRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DescribeDRTAccessRequest(_a0 *shield.DescribeDRTAccessInput) (*request.Request, *shield.DescribeDRTAccessOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.DescribeDRTAccessInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.DescribeDRTAccessOutput
+	if rf, ok := ret.Get(1).(func(*shield.DescribeDRTAccessInput) *shield.DescribeDRTAccessOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.DescribeDRTAccessOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// DescribeDRTAccessWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) DescribeDRTAccessWithContext(_a0 context.Context, _a1 *shield.DescribeDRTAccessInput, _a2 ...request.Option) (*shield.DescribeDRTAccessOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.DescribeDRTAccessOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.DescribeDRTAccessInput, ...request.Option) *shield.DescribeDRTAccessOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DescribeDRTAccessOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.DescribeDRTAccessInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DescribeEmergencyContactSettings provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DescribeEmergencyContactSettings(_a0 *shield.DescribeEmergencyContactSettingsInput) (*shield.DescribeEmergencyContactSettingsOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.DescribeEmergencyContactSettingsOutput
+	if rf, ok := ret.Get(0).(func(*shield.DescribeEmergencyContactSettingsInput) *shield.DescribeEmergencyContactSettingsOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DescribeEmergencyContactSettingsOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.DescribeEmergencyContactSettingsInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DescribeEmergencyContactSettingsRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DescribeEmergencyContactSettingsRequest(_a0 *shield.DescribeEmergencyContactSettingsInput) (*request.Request, *shield.DescribeEmergencyContactSettingsOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.DescribeEmergencyContactSettingsInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.DescribeEmergencyContactSettingsOutput
+	if rf, ok := ret.Get(1).(func(*shield.DescribeEmergencyContactSettingsInput) *shield.DescribeEmergencyContactSettingsOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.DescribeEmergencyContactSettingsOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// DescribeEmergencyContactSettingsWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) DescribeEmergencyContactSettingsWithContext(_a0 context.Context, _a1 *shield.DescribeEmergencyContactSettingsInput, _a2 ...request.Option) (*shield.DescribeEmergencyContactSettingsOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.DescribeEmergencyContactSettingsOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.DescribeEmergencyContactSettingsInput, ...request.Option) *shield.DescribeEmergencyContactSettingsOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DescribeEmergencyContactSettingsOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.DescribeEmergencyContactSettingsInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DescribeProtection provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DescribeProtection(_a0 *shield.DescribeProtectionInput) (*shield.DescribeProtectionOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.DescribeProtectionOutput
+	if rf, ok := ret.Get(0).(func(*shield.DescribeProtectionInput) *shield.DescribeProtectionOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DescribeProtectionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.DescribeProtectionInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DescribeProtectionRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DescribeProtectionRequest(_a0 *shield.DescribeProtectionInput) (*request.Request, *shield.DescribeProtectionOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.DescribeProtectionInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.DescribeProtectionOutput
+	if rf, ok := ret.Get(1).(func(*shield.DescribeProtectionInput) *shield.DescribeProtectionOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.DescribeProtectionOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// DescribeProtectionWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) DescribeProtectionWithContext(_a0 context.Context, _a1 *shield.DescribeProtectionInput, _a2 ...request.Option) (*shield.DescribeProtectionOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.DescribeProtectionOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.DescribeProtectionInput, ...request.Option) *shield.DescribeProtectionOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DescribeProtectionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.DescribeProtectionInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DescribeSubscription provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DescribeSubscription(_a0 *shield.DescribeSubscriptionInput) (*shield.DescribeSubscriptionOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.DescribeSubscriptionOutput
+	if rf, ok := ret.Get(0).(func(*shield.DescribeSubscriptionInput) *shield.DescribeSubscriptionOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DescribeSubscriptionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.DescribeSubscriptionInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DescribeSubscriptionRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DescribeSubscriptionRequest(_a0 *shield.DescribeSubscriptionInput) (*request.Request, *shield.DescribeSubscriptionOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.DescribeSubscriptionInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.DescribeSubscriptionOutput
+	if rf, ok := ret.Get(1).(func(*shield.DescribeSubscriptionInput) *shield.DescribeSubscriptionOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.DescribeSubscriptionOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// DescribeSubscriptionWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) DescribeSubscriptionWithContext(_a0 context.Context, _a1 *shield.DescribeSubscriptionInput, _a2 ...request.Option) (*shield.DescribeSubscriptionOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.DescribeSubscriptionOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.DescribeSubscriptionInput, ...request.Option) *shield.DescribeSubscriptionOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DescribeSubscriptionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.DescribeSubscriptionInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DisassociateDRTLogBucket provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DisassociateDRTLogBucket(_a0 *shield.DisassociateDRTLogBucketInput) (*shield.DisassociateDRTLogBucketOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.DisassociateDRTLogBucketOutput
+	if rf, ok := ret.Get(0).(func(*shield.DisassociateDRTLogBucketInput) *shield.DisassociateDRTLogBucketOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DisassociateDRTLogBucketOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.DisassociateDRTLogBucketInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DisassociateDRTLogBucketRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DisassociateDRTLogBucketRequest(_a0 *shield.DisassociateDRTLogBucketInput) (*request.Request, *shield.DisassociateDRTLogBucketOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.DisassociateDRTLogBucketInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.DisassociateDRTLogBucketOutput
+	if rf, ok := ret.Get(1).(func(*shield.DisassociateDRTLogBucketInput) *shield.DisassociateDRTLogBucketOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.DisassociateDRTLogBucketOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// DisassociateDRTLogBucketWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) DisassociateDRTLogBucketWithContext(_a0 context.Context, _a1 *shield.DisassociateDRTLogBucketInput, _a2 ...request.Option) (*shield.DisassociateDRTLogBucketOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.DisassociateDRTLogBucketOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.DisassociateDRTLogBucketInput, ...request.Option) *shield.DisassociateDRTLogBucketOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DisassociateDRTLogBucketOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.DisassociateDRTLogBucketInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DisassociateDRTRole provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DisassociateDRTRole(_a0 *shield.DisassociateDRTRoleInput) (*shield.DisassociateDRTRoleOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.DisassociateDRTRoleOutput
+	if rf, ok := ret.Get(0).(func(*shield.DisassociateDRTRoleInput) *shield.DisassociateDRTRoleOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DisassociateDRTRoleOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.DisassociateDRTRoleInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DisassociateDRTRoleRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) DisassociateDRTRoleRequest(_a0 *shield.DisassociateDRTRoleInput) (*request.Request, *shield.DisassociateDRTRoleOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.DisassociateDRTRoleInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.DisassociateDRTRoleOutput
+	if rf, ok := ret.Get(1).(func(*shield.DisassociateDRTRoleInput) *shield.DisassociateDRTRoleOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.DisassociateDRTRoleOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// DisassociateDRTRoleWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) DisassociateDRTRoleWithContext(_a0 context.Context, _a1 *shield.DisassociateDRTRoleInput, _a2 ...request.Option) (*shield.DisassociateDRTRoleOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.DisassociateDRTRoleOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.DisassociateDRTRoleInput, ...request.Option) *shield.DisassociateDRTRoleOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.DisassociateDRTRoleOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.DisassociateDRTRoleInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetSubscriptionState provides a mock function with given fields: _a0
+func (_m *ShieldAPI) GetSubscriptionState(_a0 *shield.GetSubscriptionStateInput) (*shield.GetSubscriptionStateOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.GetSubscriptionStateOutput
+	if rf, ok := ret.Get(0).(func(*shield.GetSubscriptionStateInput) *shield.GetSubscriptionStateOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.GetSubscriptionStateOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.GetSubscriptionStateInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetSubscriptionStateRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) GetSubscriptionStateRequest(_a0 *shield.GetSubscriptionStateInput) (*request.Request, *shield.GetSubscriptionStateOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.GetSubscriptionStateInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.GetSubscriptionStateOutput
+	if rf, ok := ret.Get(1).(func(*shield.GetSubscriptionStateInput) *shield.GetSubscriptionStateOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.GetSubscriptionStateOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// GetSubscriptionStateWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) GetSubscriptionStateWithContext(_a0 context.Context, _a1 *shield.GetSubscriptionStateInput, _a2 ...request.Option) (*shield.GetSubscriptionStateOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.GetSubscriptionStateOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.GetSubscriptionStateInput, ...request.Option) *shield.GetSubscriptionStateOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.GetSubscriptionStateOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.GetSubscriptionStateInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListAttacks provides a mock function with given fields: _a0
+func (_m *ShieldAPI) ListAttacks(_a0 *shield.ListAttacksInput) (*shield.ListAttacksOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.ListAttacksOutput
+	if rf, ok := ret.Get(0).(func(*shield.ListAttacksInput) *shield.ListAttacksOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.ListAttacksOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.ListAttacksInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListAttacksRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) ListAttacksRequest(_a0 *shield.ListAttacksInput) (*request.Request, *shield.ListAttacksOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.ListAttacksInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.ListAttacksOutput
+	if rf, ok := ret.Get(1).(func(*shield.ListAttacksInput) *shield.ListAttacksOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.ListAttacksOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// ListAttacksWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) ListAttacksWithContext(_a0 context.Context, _a1 *shield.ListAttacksInput, _a2 ...request.Option) (*shield.ListAttacksOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.ListAttacksOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.ListAttacksInput, ...request.Option) *shield.ListAttacksOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.ListAttacksOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.ListAttacksInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListProtections provides a mock function with given fields: _a0
+func (_m *ShieldAPI) ListProtections(_a0 *shield.ListProtectionsInput) (*shield.ListProtectionsOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.ListProtectionsOutput
+	if rf, ok := ret.Get(0).(func(*shield.ListProtectionsInput) *shield.ListProtectionsOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.ListProtectionsOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.ListProtectionsInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListProtectionsRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) ListProtectionsRequest(_a0 *shield.ListProtectionsInput) (*request.Request, *shield.ListProtectionsOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.ListProtectionsInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.ListProtectionsOutput
+	if rf, ok := ret.Get(1).(func(*shield.ListProtectionsInput) *shield.ListProtectionsOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.ListProtectionsOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// ListProtectionsWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) ListProtectionsWithContext(_a0 context.Context, _a1 *shield.ListProtectionsInput, _a2 ...request.Option) (*shield.ListProtectionsOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.ListProtectionsOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.ListProtectionsInput, ...request.Option) *shield.ListProtectionsOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.ListProtectionsOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.ListProtectionsInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// UpdateEmergencyContactSettings provides a mock function with given fields: _a0
+func (_m *ShieldAPI) UpdateEmergencyContactSettings(_a0 *shield.UpdateEmergencyContactSettingsInput) (*shield.UpdateEmergencyContactSettingsOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.UpdateEmergencyContactSettingsOutput
+	if rf, ok := ret.Get(0).(func(*shield.UpdateEmergencyContactSettingsInput) *shield.UpdateEmergencyContactSettingsOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.UpdateEmergencyContactSettingsOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.UpdateEmergencyContactSettingsInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// UpdateEmergencyContactSettingsRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) UpdateEmergencyContactSettingsRequest(_a0 *shield.UpdateEmergencyContactSettingsInput) (*request.Request, *shield.UpdateEmergencyContactSettingsOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.UpdateEmergencyContactSettingsInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.UpdateEmergencyContactSettingsOutput
+	if rf, ok := ret.Get(1).(func(*shield.UpdateEmergencyContactSettingsInput) *shield.UpdateEmergencyContactSettingsOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.UpdateEmergencyContactSettingsOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// UpdateEmergencyContactSettingsWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) UpdateEmergencyContactSettingsWithContext(_a0 context.Context, _a1 *shield.UpdateEmergencyContactSettingsInput, _a2 ...request.Option) (*shield.UpdateEmergencyContactSettingsOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.UpdateEmergencyContactSettingsOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.UpdateEmergencyContactSettingsInput, ...request.Option) *shield.UpdateEmergencyContactSettingsOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.UpdateEmergencyContactSettingsOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.UpdateEmergencyContactSettingsInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// UpdateSubscription provides a mock function with given fields: _a0
+func (_m *ShieldAPI) UpdateSubscription(_a0 *shield.UpdateSubscriptionInput) (*shield.UpdateSubscriptionOutput, error) {
+	ret := _m.Called(_a0)
+
+	var r0 *shield.UpdateSubscriptionOutput
+	if rf, ok := ret.Get(0).(func(*shield.UpdateSubscriptionInput) *shield.UpdateSubscriptionOutput); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.UpdateSubscriptionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*shield.UpdateSubscriptionInput) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// UpdateSubscriptionRequest provides a mock function with given fields: _a0
+func (_m *ShieldAPI) UpdateSubscriptionRequest(_a0 *shield.UpdateSubscriptionInput) (*request.Request, *shield.UpdateSubscriptionOutput) {
+	ret := _m.Called(_a0)
+
+	var r0 *request.Request
+	if rf, ok := ret.Get(0).(func(*shield.UpdateSubscriptionInput) *request.Request); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*request.Request)
+		}
+	}
+
+	var r1 *shield.UpdateSubscriptionOutput
+	if rf, ok := ret.Get(1).(func(*shield.UpdateSubscriptionInput) *shield.UpdateSubscriptionOutput); ok {
+		r1 = rf(_a0)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).(*shield.UpdateSubscriptionOutput)
+		}
+	}
+
+	return r0, r1
+}
+
+// UpdateSubscriptionWithContext provides a mock function with given fields: _a0, _a1, _a2
+func (_m *ShieldAPI) UpdateSubscriptionWithContext(_a0 context.Context, _a1 *shield.UpdateSubscriptionInput, _a2 ...request.Option) (*shield.UpdateSubscriptionOutput, error) {
+	_va := make([]interface{}, len(_a2))
+	for _i := range _a2 {
+		_va[_i] = _a2[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, _a1)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *shield.UpdateSubscriptionOutput
+	if rf, ok := ret.Get(0).(func(context.Context, *shield.UpdateSubscriptionInput, ...request.Option) *shield.UpdateSubscriptionOutput); ok {
+		r0 = rf(_a0, _a1, _a2...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*shield.UpdateSubscriptionOutput)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *shield.UpdateSubscriptionInput, ...request.Option) error); ok {
+		r1 = rf(_a0, _a1, _a2...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
diff --git a/scripts/gen_mocks.sh b/scripts/gen_mocks.sh
index edca677db..41cdc419a 100755
--- a/scripts/gen_mocks.sh
+++ b/scripts/gen_mocks.sh
@@ -13,6 +13,8 @@ mockery -name ELBV2API -dir ./vendor/github.com/aws/aws-sdk-go/service/elbv2/elb
 mockery -name IAMAPI -dir ./vendor/github.com/aws/aws-sdk-go/service/iam/iamiface
 mockery -name ResourceGroupsTaggingAPIAPI -dir ./vendor/github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/resourcegroupstaggingapiiface
 mockery -name WAFRegionalAPI -dir ./vendor/github.com/aws/aws-sdk-go/service/wafregional/wafregionaliface
+mockery -name ShieldAPI -dir ./vendor/github.com/aws/aws-sdk-go/service/shield/shieldiface
+
 
 
 mockgen -destination=./mocks/aws-alb-ingress-controller/ingress/auth/mock.go github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/ingress/auth Module


Test patch:
diff --git a/internal/alb/lb/shield_test.go b/internal/alb/lb/shield_test.go
new file mode 100644
index 000000000..ef5f61421
--- /dev/null
+++ b/internal/alb/lb/shield_test.go
@@ -0,0 +1,192 @@
+package lb
+
+import (
+	"context"
+	"errors"
+	"testing"
+
+	"k8s.io/apimachinery/pkg/util/intstr"
+
+	"github.com/aws/aws-sdk-go/service/shield"
+	"github.com/kubernetes-sigs/aws-alb-ingress-controller/internal/aws"
+	"github.com/kubernetes-sigs/aws-alb-ingress-controller/mocks"
+	"github.com/stretchr/testify/assert"
+	apiv1 "k8s.io/api/core/v1"
+	extensions "k8s.io/api/extensions/v1beta1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func buildIngress(shieldEnabled string) *extensions.Ingress {
+	defaultBackend := extensions.IngressBackend{
+		ServiceName: "default-backend",
+		ServicePort: intstr.FromInt(80),
+	}
+
+	var shieldAnnos map[string]string
+	if shieldEnabled == "true" || shieldEnabled == "false" {
+		shieldAnnos = map[string]string{
+			"alb.ingress.kubernetes.io/shield-advanced-protection": shieldEnabled,
+		}
+	} else {
+		shieldAnnos = map[string]string{}
+	}
+
+	return &extensions.Ingress{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:        "foo",
+			Namespace:   apiv1.NamespaceDefault,
+			Annotations: shieldAnnos,
+		},
+		Spec: extensions.IngressSpec{
+			Backend: &extensions.IngressBackend{
+				ServiceName: "default-backend",
+				ServicePort: intstr.FromInt(80),
+			},
+			Rules: []extensions.IngressRule{
+				{
+					Host: "foo.bar.com",
+					IngressRuleValue: extensions.IngressRuleValue{
+						HTTP: &extensions.HTTPIngressRuleValue{
+							Paths: []extensions.HTTPIngressPath{
+								{
+									Path:    "/foo",
+									Backend: defaultBackend,
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+}
+
+func Test_defaultShieldController_Reconcile(t *testing.T) {
+	for _, tc := range []struct {
+		Name                        string
+		ShieldAvailableResponse     bool
+		ShieldAvailableError        error
+		GetProtectionResponse       *shield.Protection
+		GetProtectionError          error
+		CreateProtectionResponse    *shield.CreateProtectionOutput
+		CreateProtectionError       error
+		DeleteProtectionResponse    *shield.DeleteProtectionOutput
+		DeleteProtectionError       error
+		Expected                    error
+		ExpectedError               error
+		LoadBalancerARN             string
+		IngressAnnocation           *extensions.Ingress
+		ShieldAvailableTimesCalled  int
+		GetProtectionTimesCalled    int
+		CreateProtectionTimesCalled int
+		DeleteProtectionTimesCalled int
+	}{
+		{
+			Name:                    "No operations, already protected",
+			ShieldAvailableResponse: true,
+			ShieldAvailableError:    nil,
+			GetProtectionResponse: &shield.Protection{
+				Id:          aws.String("ProtectionId"),
+				Name:        aws.String(protectionName),
+				ResourceArn: aws.String("arn:lb"),
+			},
+			GetProtectionError:          nil,
+			Expected:                    nil,
+			LoadBalancerARN:             "arn:lb",
+			IngressAnnocation:           buildIngress("true"),
+			ShieldAvailableTimesCalled:  1,
+			CreateProtectionTimesCalled: 0,
+			DeleteProtectionTimesCalled: 0,
+		},
+		{
+			Name:                        "No operations, nothing to protect",
+			ShieldAvailableResponse:     true,
+			ShieldAvailableError:        nil,
+			GetProtectionResponse:       nil,
+			GetProtectionError:          nil,
+			Expected:                    nil,
+			LoadBalancerARN:             "arn:lb",
+			IngressAnnocation:           buildIngress(""),
+			ShieldAvailableTimesCalled:  0,
+			CreateProtectionTimesCalled: 0,
+			DeleteProtectionTimesCalled: 0,
+		},
+		{
+			Name:                    "No operations, protection externally managed",
+			ShieldAvailableResponse: true,
+			ShieldAvailableError:    nil,
+			GetProtectionResponse: &shield.Protection{
+				Id:          aws.String("ProtectionId"),
+				Name:        aws.String("protection enabled manually"),
+				ResourceArn: aws.String("arn:lb"),
+			},
+			GetProtectionError:          nil,
+			Expected:                    nil,
+			LoadBalancerARN:             "arn:lb",
+			IngressAnnocation:           buildIngress("false"),
+			ShieldAvailableTimesCalled:  1,
+			CreateProtectionTimesCalled: 0,
+			DeleteProtectionTimesCalled: 0,
+		},
+		{
+			Name:                        "Protection enabled, no active subscription",
+			ShieldAvailableResponse:     false,
+			ShieldAvailableError:        nil,
+			GetProtectionResponse:       nil,
+			GetProtectionError:          nil,
+			Expected:                    errors.New("unable to create shield advanced protection for loadBalancer arn:lb, shield advanced subscription is not active"),
+			LoadBalancerARN:             "arn:lb",
+			IngressAnnocation:           buildIngress("true"),
+			ShieldAvailableTimesCalled:  1,
+			CreateProtectionTimesCalled: 0,
+			DeleteProtectionTimesCalled: 0,
+		},
+		{
+			Name:                        "Enable protection",
+			ShieldAvailableResponse:     true,
+			ShieldAvailableError:        nil,
+			GetProtectionResponse:       nil,
+			GetProtectionError:          nil,
+			Expected:                    nil,
+			LoadBalancerARN:             "arn:lb",
+			IngressAnnocation:           buildIngress("true"),
+			ShieldAvailableTimesCalled:  1,
+			CreateProtectionTimesCalled: 1,
+			DeleteProtectionTimesCalled: 0,
+		},
+		{
+			Name:                    "Disable protection",
+			ShieldAvailableResponse: true,
+			ShieldAvailableError:    nil,
+			GetProtectionResponse: &shield.Protection{
+				Id:          aws.String("ProtectionId"),
+				Name:        aws.String(protectionName),
+				ResourceArn: aws.String("arn:lb"),
+			},
+			GetProtectionError:          nil,
+			Expected:                    nil,
+			LoadBalancerARN:             "arn:lb",
+			IngressAnnocation:           buildIngress("false"),
+			ShieldAvailableTimesCalled:  1,
+			CreateProtectionTimesCalled: 0,
+			DeleteProtectionTimesCalled: 1,
+		},
+	} {
+		t.Run(tc.Name, func(t *testing.T) {
+			ctx := context.Background()
+			cloud := &mocks.CloudAPI{}
+
+			cloud.On("ShieldAvailable", ctx).Return(tc.ShieldAvailableResponse, tc.ShieldAvailableError)
+			cloud.On("GetProtection", ctx, aws.String(tc.LoadBalancerARN)).Return(tc.GetProtectionResponse, tc.GetProtectionError)
+			cloud.On("DeleteProtection", ctx, aws.String("ProtectionId")).Return(tc.DeleteProtectionResponse, tc.DeleteProtectionError)
+			cloud.On("CreateProtection", ctx, aws.String(tc.LoadBalancerARN), aws.String(protectionName)).Return(tc.CreateProtectionResponse, tc.CreateProtectionError)
+
+			controller := NewShieldController(cloud)
+			err := controller.Reconcile(ctx, tc.LoadBalancerARN, tc.IngressAnnocation)
+			assert.Equal(t, tc.Expected, err)
+			cloud.AssertNumberOfCalls(t, "ShieldAvailable", tc.ShieldAvailableTimesCalled)
+			cloud.AssertNumberOfCalls(t, "CreateProtection", tc.CreateProtectionTimesCalled)
+			cloud.AssertNumberOfCalls(t, "DeleteProtection", tc.DeleteProtectionTimesCalled)
+		})
+	}
+}
diff --git a/internal/aws/shield_test.go b/internal/aws/shield_test.go
new file mode 100644
index 000000000..dea3cb750
--- /dev/null
+++ b/internal/aws/shield_test.go
@@ -0,0 +1,230 @@
+package aws
+
+import (
+	"context"
+	"errors"
+	"testing"
+
+	"github.com/aws/aws-sdk-go/aws/awserr"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/service/shield"
+	"github.com/kubernetes-sigs/aws-alb-ingress-controller/mocks"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestCloud_GetSubscriptionStatus(t *testing.T) {
+	for _, tc := range []struct {
+		Name                                    string
+		GetSubscriptionStateWithContextResponse *shield.GetSubscriptionStateOutput
+		GetSubscriptionStateWithContextError    error
+		Expected                                *shield.GetSubscriptionStateOutput
+		ExpectedError                           error
+	}{
+		{
+			Name:                                    "No error from GetSubscriptionStateWithContext",
+			GetSubscriptionStateWithContextResponse: &shield.GetSubscriptionStateOutput{SubscriptionState: String("ACTIVE")},
+			GetSubscriptionStateWithContextError:    nil,
+			Expected:                                &shield.GetSubscriptionStateOutput{SubscriptionState: String("ACTIVE")},
+			ExpectedError:                           nil,
+		},
+		{
+			Name:                                 "Error from GetSubscriptionStateWithContext, unknown error",
+			GetSubscriptionStateWithContextError: errors.New(shield.ErrCodeInternalErrorException),
+			Expected:                             nil,
+			ExpectedError:                        errors.New(shield.ErrCodeInternalErrorException),
+		},
+	} {
+		t.Run(tc.Name, func(t *testing.T) {
+			ctx := context.Background()
+			cloudsvc := &mocks.ShieldAPI{}
+			cloudsvc.On("GetSubscriptionStateWithContext", ctx, &shield.GetSubscriptionStateInput{}).Return(tc.GetSubscriptionStateWithContextResponse, tc.GetSubscriptionStateWithContextError)
+
+			cloud := &Cloud{
+				shield: cloudsvc,
+			}
+
+			b, err := cloud.GetSubscriptionStatus(ctx)
+			assert.Equal(t, tc.Expected, b)
+			assert.Equal(t, tc.ExpectedError, err)
+			cloudsvc.AssertExpectations(t)
+		})
+	}
+}
+
+func TestCloud_ShieldAvailable(t *testing.T) {
+	for _, tc := range []struct {
+		Name                                    string
+		GetSubscriptionStateWithContextResponse *shield.GetSubscriptionStateOutput
+		GetSubscriptionStateWithContextError    error
+		Expected                                bool
+		ExpectedError                           error
+	}{
+		{
+			Name:                                    "No error from ShieldAvailable, Shield Advanced subscription active",
+			GetSubscriptionStateWithContextResponse: &shield.GetSubscriptionStateOutput{SubscriptionState: String("ACTIVE")},
+			GetSubscriptionStateWithContextError:    nil,
+			Expected:                                true,
+			ExpectedError:                           nil,
+		},
+		{
+			Name:                                    "No error from ShieldAvailable, Shield Advanced subscription inactive",
+			GetSubscriptionStateWithContextResponse: &shield.GetSubscriptionStateOutput{SubscriptionState: String("INACTIVE")},
+			GetSubscriptionStateWithContextError:    nil,
+			Expected:                                false,
+			ExpectedError:                           nil,
+		},
+		{
+			Name:                                 "Error from GetSubscriptionStateWithContext, unknown error",
+			GetSubscriptionStateWithContextError: errors.New(shield.ErrCodeInternalErrorException),
+			Expected:                             false,
+			ExpectedError:                        errors.New(shield.ErrCodeInternalErrorException),
+		},
+	} {
+		t.Run(tc.Name, func(t *testing.T) {
+			ctx := context.Background()
+			cloudsvc := &mocks.ShieldAPI{}
+			cloudsvc.On("GetSubscriptionStateWithContext", ctx, &shield.GetSubscriptionStateInput{}).Return(tc.GetSubscriptionStateWithContextResponse, tc.GetSubscriptionStateWithContextError)
+
+			cloud := &Cloud{
+				shield: cloudsvc,
+			}
+
+			b, err := cloud.ShieldAvailable(ctx)
+			assert.Equal(t, tc.Expected, b)
+			assert.Equal(t, tc.ExpectedError, err)
+			cloudsvc.AssertExpectations(t)
+		})
+	}
+}
+
+func TestCloud_GetProtection(t *testing.T) {
+	resourceArn := aws.String("arn")
+
+	for _, tc := range []struct {
+		Name                                  string
+		DescribeProtectionWithContextResponse *shield.DescribeProtectionOutput
+		DescribeProtectionWithContextError    error
+		error
+		Expected      *shield.Protection
+		ExpectedError error
+	}{
+		{
+			Name:                                  "No error from DescribeProtection",
+			DescribeProtectionWithContextResponse: &shield.DescribeProtectionOutput{Protection: &shield.Protection{}},
+			DescribeProtectionWithContextError:    nil,
+			Expected:                              &shield.Protection{},
+		},
+		{
+			Name:                               "Error from DescribeProtection, protection doesn't exist",
+			DescribeProtectionWithContextError: awserr.New(shield.ErrCodeResourceNotFoundException, "not found", nil),
+			Expected:                           nil,
+			ExpectedError:                      nil,
+		},
+		{
+			Name:                               "Error from DescribeProtection, internal server error",
+			DescribeProtectionWithContextError: errors.New(shield.ErrCodeInternalErrorException),
+			ExpectedError:                      errors.New(shield.ErrCodeInternalErrorException),
+		},
+	} {
+		t.Run(tc.Name, func(t *testing.T) {
+			ctx := context.Background()
+			cloudsvc := &mocks.ShieldAPI{}
+			cloudsvc.On("DescribeProtectionWithContext", ctx, &shield.DescribeProtectionInput{
+				ResourceArn: resourceArn,
+			}).Return(tc.DescribeProtectionWithContextResponse, tc.DescribeProtectionWithContextError)
+
+			cloud := &Cloud{
+				shield: cloudsvc,
+			}
+
+			output, err := cloud.GetProtection(ctx, resourceArn)
+			assert.Equal(t, tc.Expected, output)
+			assert.Equal(t, tc.ExpectedError, err)
+			cloudsvc.AssertExpectations(t)
+		})
+	}
+}
+
+func TestCloud_CreateProtection(t *testing.T) {
+	resourceArn := aws.String("arn")
+
+	for _, tc := range []struct {
+		Name                                string
+		CreateProtectionWithContextResponse *shield.CreateProtectionOutput
+		CreateProtectionWithContextError    error
+		Expected                            *shield.CreateProtectionOutput
+		ExpectedError                       error
+	}{
+		{
+			Name:                                "No error from API",
+			CreateProtectionWithContextResponse: &shield.CreateProtectionOutput{},
+			CreateProtectionWithContextError:    nil,
+			Expected:                            &shield.CreateProtectionOutput{},
+		},
+		{
+			Name:                             "Error from API, concurrent modification",
+			CreateProtectionWithContextError: errors.New("api query failed"),
+			ExpectedError:                    errors.New("api query failed"),
+		},
+	} {
+		t.Run(tc.Name, func(t *testing.T) {
+			ctx := context.Background()
+			shieldsvc := &mocks.ShieldAPI{}
+			shieldsvc.On("CreateProtectionWithContext", ctx, &shield.CreateProtectionInput{
+				Name:        aws.String("managed by aws-alb-ingress-controller"),
+				ResourceArn: resourceArn,
+			}).Return(tc.CreateProtectionWithContextResponse, tc.CreateProtectionWithContextError)
+
+			cloud := &Cloud{
+				shield: shieldsvc,
+			}
+
+			output, err := cloud.CreateProtection(ctx, resourceArn, aws.String("managed by aws-alb-ingress-controller"))
+			assert.Equal(t, tc.Expected, output)
+			assert.Equal(t, tc.ExpectedError, err)
+			shieldsvc.AssertExpectations(t)
+		})
+	}
+}
+
+func TestCloud_DeleteProtection(t *testing.T) {
+	protectionID := aws.String("protectionID")
+
+	for _, tc := range []struct {
+		Name                                string
+		DeleteProtectionWithContextResponse *shield.DeleteProtectionOutput
+		DeleteProtectionWithContextError    error
+		Expected                            *shield.DeleteProtectionOutput
+		ExpectedError                       error
+	}{
+		{
+			Name:                                "No error from API",
+			DeleteProtectionWithContextResponse: &shield.DeleteProtectionOutput{},
+			DeleteProtectionWithContextError:    nil,
+			Expected:                            &shield.DeleteProtectionOutput{},
+		},
+		{
+			Name:                             "Error from API",
+			DeleteProtectionWithContextError: errors.New("api query failed"),
+			ExpectedError:                    errors.New("api query failed"),
+		},
+	} {
+		t.Run(tc.Name, func(t *testing.T) {
+			ctx := context.Background()
+			shieldsvc := &mocks.ShieldAPI{}
+			shieldsvc.On("DeleteProtectionWithContext", ctx, &shield.DeleteProtectionInput{
+				ProtectionId: protectionID,
+			}).Return(tc.DeleteProtectionWithContextResponse, tc.DeleteProtectionWithContextError)
+
+			cloud := &Cloud{
+				shield: shieldsvc,
+			}
+
+			output, err := cloud.DeleteProtection(ctx, protectionID)
+			assert.Equal(t, tc.Expected, output)
+			assert.Equal(t, tc.ExpectedError, err)
+			shieldsvc.AssertExpectations(t)
+		})
+	}
+}
diff --git a/tester/test-config.yaml b/tester/test-config.yaml
index 8c5d385b6..92c7201fd 100644
--- a/tester/test-config.yaml
+++ b/tester/test-config.yaml
@@ -121,6 +121,18 @@ cluster:
                   "waf:GetWebACL"
                 ],
                 "Resource": "*"
+              },
+              {
+                "Effect": "Allow",
+                "Action": [
+                  "shield:DescribeProtection",
+                  "shield:GetSubscriptionState",
+                  "shield:DeleteProtection",
+                  "shield:CreateProtection",
+                  "shield:DescribeSubscription",
+                  "shield:ListProtections"
+                ],
+                "Resource": "*"
               }
             ]