From 7d7c4f43b91c711e4be0aabefb17cbd71c620c51 Mon Sep 17 00:00:00 2001 From: Adam Schwartz Date: Thu, 10 Sep 2020 18:32:31 -0400 Subject: [PATCH] terraform content cleanup/rewrite - add missing h1s - remove `/terraform` pathPrefix from internal links in md - use where appropriate - re-order sidenav - add missing languages to code blocks - convert getting started into index --- .../importing-cloudflare-resources.md | 25 ++++---- .../src/content/advanced-topics/index.md | 14 +---- .../advanced-topics/provider-customization.md | 19 ++---- .../content/advanced-topics/sharing-state.md | 5 -- .../src/content/getting-started/index.md | 9 --- products/terraform/src/content/index.md | 24 +++++++- .../{getting-started => }/installing.md | 22 ++++--- .../src/content/tutorial/hello-world.md | 23 ++++---- .../terraform/src/content/tutorial/index.md | 58 ++++++++++--------- .../src/content/tutorial/load-balance.md | 29 +++++----- .../src/content/tutorial/page-rules.md | 24 ++++---- .../src/content/tutorial/rate-limit.md | 8 ++- .../src/content/tutorial/roll-back.md | 32 +++++----- .../src/content/tutorial/source-control.md | 28 ++++----- .../src/content/tutorial/zone-settings.md | 20 ++++--- 15 files changed, 179 insertions(+), 161 deletions(-) delete mode 100644 products/terraform/src/content/advanced-topics/sharing-state.md delete mode 100644 products/terraform/src/content/getting-started/index.md rename products/terraform/src/content/{getting-started => }/installing.md (84%) diff --git a/products/terraform/src/content/advanced-topics/importing-cloudflare-resources.md b/products/terraform/src/content/advanced-topics/importing-cloudflare-resources.md index 5a1bc5e7f1..1f6316f4f6 100644 --- a/products/terraform/src/content/advanced-topics/importing-cloudflare-resources.md +++ b/products/terraform/src/content/advanced-topics/importing-cloudflare-resources.md @@ -1,15 +1,11 @@ ---- -title: Importing Cloudflare Resources -alwaysopen: true -weight: 20 ---- +# Importing Cloudflare resources An important point to understand about Terraform is that it is only able to manage configuration that it created, or was explicitly told about after the fact. The reason for this limitation is that Terraform expects to be authoritative for the resources its manages. It relies on 2 types of files to understand what resources it controls, and what state they are in. This is how it determines when and how to make changes. -1. A [configuration file](https://www.terraform.io/docs/configuration/index.html) (ending in .tf) that defines the configuration of resources for Terraform to manage. This is what you worked with in the tutorial steps. +1. A [configuration file](https://www.terraform.io/docs/configuration/index.html) (ending in .tf) that defines the configuration of resources for Terraform to manage. This is what you worked with in the tutorial steps. 2. A local [state file](https://www.terraform.io/docs/state/) that maps the resource names defined in your configuration file, e.g., cloudflare_load_balancer.www-lb to the resources that exist in Cloudflare. -When Terraform makes calls to Cloudflare's API to create new resources as illustrated in the [tutorial](/terraform/tutorial), it persists those IDs to a state file. By default, the `terraform.tfstate` file in your directory is used, but this can also be a [remote location](https://www.terraform.io/docs/state/remote.html). These IDs are later looked up and refreshed when you call `terraform plan` and `terraform apply`. +When Terraform makes calls to Cloudflare's API to create new resources as illustrated in the [tutorial](/tutorial), it persists those IDs to a state file. By default, the `terraform.tfstate` file in your directory is used, but this can also be a [remote location](https://www.terraform.io/docs/state/remote.html). These IDs are later looked up and refreshed when you call `terraform plan` and `terraform apply`. If you've configured Cloudflare through other means, e.g., by logging into the Cloudflare Dashboard or making `curl` calls to api.cloudflare.com, Terraform does not (yet) have these resource IDs in the state file. To manage this preexisting configuration you will need to first i) reproduce the configuration in your config file and; ii) import resources one-by-one by providing their IDs and resource names. @@ -49,7 +45,7 @@ The list of supported resources currently are: * [zone](https://www.terraform.io/docs/providers/cloudflare/r/zone.html) * [zone_lockdown](https://www.terraform.io/docs/providers/cloudflare/r/zone_lockdown.html) * [zone_settings_override](https://www.terraform.io/docs/providers/cloudflare/r/zone_settings_override.html) - + ## Importing existing Cloudflare resources As mentioned, to start managing existing Cloudflare resources in Terraform, e.g., DNS records, you need two things: @@ -59,7 +55,8 @@ As mentioned, to start managing existing Cloudflare resources in Terraform, e.g. ### 1. Generate Terraform Configuration with Cf-Terraforming If you don't have a Terraform configuration file defined, all you need is the provider blocked defined as follows: -``` + +```tf provider 'cloudflare' { # Cloudflare email saved in $CLOUDFLARE_EMAIL # Cloudflare API key saved in $CLOUDFLARE_TOKEN @@ -70,14 +67,14 @@ Remember to keep your credentials saved in environment variables or terraform au We start by making a call to Cf-Terraforming to enumerate the Terraform configuration for the DNS records for the zone we want to manage with Terraform. -Note: The below command assumes you run the tool from `{GOPATH}/src/github.com/cloudflare/cf-terraforming`. If pulled with `go get` and if `$GOPATH/bin` is in your `$PATH` you should be able to just run the tool with `$ cf-terraforming `. +Note: The below command assumes you run the tool from `{GOPATH}/src/github.com/cloudflare/cf-terraforming`. If pulled with `go get` and if `$GOPATH/bin` is in your `$PATH` you should be able to just run the tool with `$ cf-terraforming `. ``` $ go run cmd/cf-terraforming/main.go --email $CLOUDFLARE_EMAIL --key $CLOUDFLARE_TOKEN -z 1109d899a5ff5fd74bc01e581693685a record > importing-example.tf ``` If output to standard out, the result would look like the below. In this case we directly imported the configuration into our Terraform configuration file `importing-state.tf`. -``` +```tf resource "cloudflare_record" "mitigateddos_net_mitigateddos_net" { domain = "mitigateddos.net" @@ -125,7 +122,7 @@ resource "cloudflare_record" "mitigateddos_net_a123_mitigateddos_net_2" { Calling terraform `plan` now will attempt to create these resources as if they didn't exist which isn't exactly what we desire. -``` +```sh $ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be @@ -214,7 +211,7 @@ Soon cf-terraforming will also allow you to import tfstate for the same resource Hint: If you run cf-terraforming with `-v` to stdout, we will log the resource ids in Cloudflare which can help with running Terraform `import`. -``` +```sh $ terraform import cloudflare_record.mitigateddos_net_mitigateddos_net mitigateddos.net/6702ceac85496311b1fa86a4ecc2fd47 cloudflare_record.mitigateddos_net_mitigateddos_net: Importing from ID "mitigateddos.net/6702ceac85496311b1fa86a4ecc2fd47"... cloudflare_record.mitigateddos_net_mitigateddos_net: Import complete! @@ -262,7 +259,7 @@ your Terraform state and will henceforth be managed by Terraform. Now when we run `terraform plan` it no longer wants to (re-)create the above records. -``` +```sh $ terraform plan | grep changes No changes. Infrastructure is up-to-date. ``` diff --git a/products/terraform/src/content/advanced-topics/index.md b/products/terraform/src/content/advanced-topics/index.md index b251001a15..49a3ef410f 100644 --- a/products/terraform/src/content/advanced-topics/index.md +++ b/products/terraform/src/content/advanced-topics/index.md @@ -1,15 +1,7 @@ --- -title: Advanced Topics -alwaysopen: true -weight: 50 -hidden: false -showNew: false +order: 3 --- -### [Importing Cloudflare Resources](/terraform/advanced-topics/importing-cloudflare-resources/) - -* Working with existing Cloudflare configuration +# Advanced topics -### [Provider Customization](/terraform/advanced-topics/provider-customization/) - -* Customizing the Cloudflare Terraform provider, e.g., adjusting speed and backoff of API calls + diff --git a/products/terraform/src/content/advanced-topics/provider-customization.md b/products/terraform/src/content/advanced-topics/provider-customization.md index 3c9cbe23ab..fe665ef7d9 100644 --- a/products/terraform/src/content/advanced-topics/provider-customization.md +++ b/products/terraform/src/content/advanced-topics/provider-customization.md @@ -1,31 +1,24 @@ ---- -title: Provider Customization -weight: 40 ---- +# Provider customization - -Terraform communicates with cloud and edge provider APIs such as Cloudflare through modules known as "providers". These providers are [installed automatically](/terraform/tutorial/hello-world/#2-initializing-terraform-and-the-cloudflare-provider) when you run `terraform init` in a directory that has a `.tf` file containing a provider. Typically, the only required parameters to the provider are what's requried to authenticate. In many cases, however, it may make sense to customize the provider to your needs. Below we examine some of the [optional settings](https://www.terraform.io/docs/providers/cloudflare/#argument-reference) that can be passed to the Cloudflare Provider. +Terraform communicates with cloud and edge provider APIs such as Cloudflare through modules known as "providers". These providers are [installed automatically](/tutorial/hello-world/#2-initializing-terraform-and-the-cloudflare-provider) when you run `terraform init` in a directory that has a `.tf` file containing a provider. Typically, the only required parameters to the provider are what's requried to authenticate. In many cases, however, it may make sense to customize the provider to your needs. Below we examine some of the [optional settings](https://www.terraform.io/docs/providers/cloudflare/#argument-reference) that can be passed to the Cloudflare Provider. ## Adjusting the default Cloudflare provider settings The Cloudflare Terraform provider can be customized through the use of configuration parameters, specified either in your `.tf` configuration files or via environment variables, e.g., `$CLOUDFLARE_RPS`. Using environment variables may make sense when running Terraform from a CI/CD system, or when the change is temporary and doesn't need to be persisted in your configuration history. ### i. Increasing the frequency of API requests + The `api.cloudflare.com` endpoint has a default rate limit of 1200 calls per 5 minute period (as of time of writing; see rate limiting section under [Requests](https://api.cloudflare.com/#getting-started-requests) for updates). Enterprise customers may request this limit be increased by contacting their Customer Success Manager. Even with an updated rate limit, Terraform will need to stay under this threshold otherwise the Cloudflare API will respond with `HTTP 429/Too Many Requests` responses. When it does, the Cloudflare Terraform provider will back off before retrying. All of these figures can be customized, as shown below. -``` +```sh $ export CLOUDFLARE_RPS= $ export CLOUDFLARE_API_CLIENT_LOGGING=true ``` - - - - - diff --git a/products/terraform/src/content/advanced-topics/sharing-state.md b/products/terraform/src/content/advanced-topics/sharing-state.md deleted file mode 100644 index d6d8a28900..0000000000 --- a/products/terraform/src/content/advanced-topics/sharing-state.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Sharing State ---- - -_TBD_ \ No newline at end of file diff --git a/products/terraform/src/content/getting-started/index.md b/products/terraform/src/content/getting-started/index.md deleted file mode 100644 index af0cb547e5..0000000000 --- a/products/terraform/src/content/getting-started/index.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Getting Started -alwaysopen: true -weight: 10 ---- - -See [Installing Terraform](/terraform/getting-started/installing/). - -Report Terraform config issues via [Github](https://github.com/terraform-providers/terraform-provider-cloudflare/issues). diff --git a/products/terraform/src/content/index.md b/products/terraform/src/content/index.md index 00d83664d4..2310908a57 100644 --- a/products/terraform/src/content/index.md +++ b/products/terraform/src/content/index.md @@ -1,7 +1,27 @@ --- +title: Welcome order: 0 +type: overview --- -# Welcome + -TODO... +# Cloudflare Terraform documentation + +Configure Cloudflare using HashiCorp's “Infrastructure as Code” tool, Terraform. + +With Cloudflare’s Terraform provider, you can manage your edge using the same familiar tools you use to automate the rest of your infrastructure. Define and store configuration in source code repositories like GitHub, track and version changes over time, and roll back when needed—all without needing to learn the Cloudflare APIs. + +-------------------------------- + +## Installing + +See [Installing Terraform](/installing/). + +-------------------------------- + +## Issues + +Report Terraform config issues via [Github](https://github.com/terraform-providers/terraform-provider-cloudflare/issues). + + diff --git a/products/terraform/src/content/getting-started/installing.md b/products/terraform/src/content/installing.md similarity index 84% rename from products/terraform/src/content/getting-started/installing.md rename to products/terraform/src/content/installing.md index 9b187ef826..80a38472ee 100644 --- a/products/terraform/src/content/getting-started/installing.md +++ b/products/terraform/src/content/installing.md @@ -1,16 +1,19 @@ --- -title: Installing Terraform -alwaysopen: true -weight: 10 +title: Installing +order: 1 --- +# Installing Terraform + The installation process for Terraform is extremely simple as it ships as a single binary file. Official instructions for installing Terraform can be found [here](https://www.terraform.io/intro/getting-started/install.html), with some examples provided below for popular operating systems. +-------------------------------- + ## Mac The easiest way to install Terraform on macOS is with Homebrew: -``` +```sh $ brew install terraform ==> Downloading https://homebrew.bintray.com/bottles/terraform-0.11.6.sierra.bottle.tar.gz @@ -22,16 +25,18 @@ $ terraform version Terraform v0.11.6 ``` +-------------------------------- + ## Linux On Linux, you just need to download and place the binary in your $PATH: -``` +```sh $ wget -q https://releases.hashicorp.com/terraform/0.11.6/terraform_0.11.6_linux_amd64.zip $ unzip terraform_0.11.6_linux_amd64.zip Archive: terraform_0.11.6_linux_amd64.zip - inflating: terraform + inflating: terraform $ sudo mv terraform /usr/local/bin/terraform @@ -39,12 +44,15 @@ $ terraform version Terraform v0.11.6 ``` +-------------------------------- + ## Windows 1. Download the 32 or 64-bit executable from the [Terraform Download](https://www.terraform.io/downloads.html) page. 2. Unzip and place terraform.exe somewhere in your path. +-------------------------------- ## Other -Additional installers can be found at https://www.terraform.io/downloads.html. \ No newline at end of file +Additional installers can be found at https://www.terraform.io/downloads.html. diff --git a/products/terraform/src/content/tutorial/hello-world.md b/products/terraform/src/content/tutorial/hello-world.md index 4e426efd52..6df0cd9368 100644 --- a/products/terraform/src/content/tutorial/hello-world.md +++ b/products/terraform/src/content/tutorial/hello-world.md @@ -1,17 +1,19 @@ --- -title: Step 1 - Hello World -weight: 10 +title: 1 – Hello World +order: 1 --- +# Hello World + Let's say you have a web server for your domain that’s accessible on 203.0.113.10. You just signed up your domain, example.com, on Cloudflare and want to manage everything in Terraform. -This tutorial step shows you how to get started. Before you do so, make sure you've completed the [Getting Started](/terraform/getting-started/) steps. +This tutorial step shows you how to get started. Before you do so, make sure you've completed the [Getting Started](/getting-started/) steps. ## 1. Defining your first Terraform config file First we'll create a initial Terraform config file. Any files ending in `.tf` will be processed by Terraform. As you configuration gets more complex you'll want to split the config into separate files and modules, but for now we'll proceed with a single file: -```bash +```sh $ cat > cloudflare.tf <<'EOF' provider "cloudflare" { email = "you@example.com" @@ -36,7 +38,7 @@ EOF Now that you’ve created your basic configuration in HCL, let’s initialize Terraform and ask it to apply the configuration to Cloudflare. -``` +```sh $ terraform init Initializing provider plugins... @@ -66,7 +68,7 @@ commands will detect it and remind you to do so if necessary. When you run terraform init, any plugins required, such as the Cloudflare Terraform provider, are automatically downloaded and saved locally to a .terraform directory: -``` +```sh $ find .terraform/ .terraform/ .terraform//plugins @@ -78,7 +80,7 @@ $ find .terraform/ ## 3. Reviewing the execution plan With the Cloudflare provider installed, let’s ask Terraform what changes it’s planning to make to your Cloudflare account so it matches the configuration you previously defined: -``` +```sh $ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be @@ -124,7 +126,7 @@ As you can see in the above “execution plan”, Terraform is going to create a The plan command is important, as it allows you to preview the changes for accuracy before actually making them. Once you’re comfortable with the execution plan, it’s time to apply it: -``` +```sh $ terraform apply --auto-approve cloudflare_record.www: Creating... created_on: "" => "" @@ -154,7 +156,7 @@ Logging back into the Cloudflare Dashboard and selecting the DNS tab, I can see If you’d like to see the full results returned from the API call (including the default values that you didn’t specify but let Terraform compute), you can run terraform show: -``` +```sh $ terraform show cloudflare_record.www: id = c38d3103767284e7cd14d5dad3ab8668 @@ -176,8 +178,7 @@ cloudflare_record.www: zone_id = e2e6391340be87a3726f91fc4148b122 ``` - -``` +```sh $ curl https://www.example.com Hello, this is 203.0.113.10! ``` diff --git a/products/terraform/src/content/tutorial/index.md b/products/terraform/src/content/tutorial/index.md index 7588bd57d0..6d7a4b16cc 100644 --- a/products/terraform/src/content/tutorial/index.md +++ b/products/terraform/src/content/tutorial/index.md @@ -1,46 +1,50 @@ --- -title: Tutorial -alwaysopen: true -weight: 15 +order: 2 --- -_This tutorial assumes that you have installed Terraform. If you haven’t, please visit the Terraform Downloads page._ +# Tutorial + + Each example builds on the last, so you should start from the top. Here are the topics and resources covered per tutorial step: -### [Step 1 - Hello World](/terraform/tutorial/hello-world/) +## [1 – Hello World](/tutorial/hello-world/) -* Brief intro -* Introduction of terraform init, plan, apply, and show. -* Resources covered: DNS +- Brief intro +- Introduction of terraform init, plan, apply, and show. +- Resources covered: DNS -### [Step 2 - Tracking your history](/terraform/tutorial/source-control/) +## [2 – Tracking your history](/tutorial/source-control/) -* Storing Cloudflare configuration in source control +- Storing Cloudflare configuration in source control -### [Step 3 - HTTPS all the things](/terraform/tutorial/zone-settings/) +## [3 – HTTPS all the things](/tutorial/zone-settings/) -* Modifying zone settings -* Resources covered: [zone settings override](https://www.terraform.io/docs/providers/cloudflare/r/zone_settings_override.html) +- Modifying zone settings +- Resources covered: [zone settings override](https://www.terraform.io/docs/providers/cloudflare/r/zone_settings_override.html) -### [Step 4 - Woah, slow down there](/terraform/tutorial/rate-limit/) +## [4 – Woah, slow down there](/tutorial/rate-limit/) -* Adding rate limiting rules -* Resource covered: [rate limit](https://www.terraform.io/docs/providers/cloudflare/r/rate_limit.html) +- Adding rate limiting rules +- Resource covered: [rate limit](https://www.terraform.io/docs/providers/cloudflare/r/rate_limit.html) -### [Step 5 - Sharing the load](/terraform/tutorial/load-balance/) +## [5 – Sharing the load](/tutorial/load-balance/) -* Adding load balancing rules -* Resources covered: [load balancer](https://www.terraform.io/docs/providers/cloudflare/r/load_balancer.html), [load balancer pool](https://www.terraform.io/docs/providers/cloudflare/r/load_balancer_pool.html), [load balancer monitor](https://www.terraform.io/docs/providers/cloudflare/r/load_balancer_monitor.html) +- Adding load balancing rules +- Resources covered: [load balancer](https://www.terraform.io/docs/providers/cloudflare/r/load_balancer.html), [load balancer pool](https://www.terraform.io/docs/providers/cloudflare/r/load_balancer_pool.html), [load balancer monitor](https://www.terraform.io/docs/providers/cloudflare/r/load_balancer_monitor.html) -### [Step 6 - Making some exceptions](/terraform/tutorial/page-rules/) -* Add page rule -* Resources covered: [page rules](https://www.terraform.io/docs/providers/cloudflare/r/page_rule.html) +## [6 – Making some exceptions](/tutorial/page-rules/) -* WAF off for specific path: /abuse-report -* Forwarding URL (301) from blog to example.com/blog +- Add page rule +- Resources covered: [page rules](https://www.terraform.io/docs/providers/cloudflare/r/page_rule.html) +- WAF off for specific path: /abuse-report +- Forwarding URL (301) from blog to example.com/blog -### [Step 7 - On final thought, let's roll some of that back](/terraform/tutorial/roll-back/) +## [7 – On final thought, let’s roll some of that back](/tutorial/roll-back/) -* Reviewing change history -* Rolling back changes +- Reviewing change history +- Rolling back changes diff --git a/products/terraform/src/content/tutorial/load-balance.md b/products/terraform/src/content/tutorial/load-balance.md index 0dd48fe640..d9e07378b6 100644 --- a/products/terraform/src/content/tutorial/load-balance.md +++ b/products/terraform/src/content/tutorial/load-balance.md @@ -1,10 +1,11 @@ --- -title: Step 5 - Sharing the load -weight: 50 +title: 5 – Sharing the load +order: 5 --- +# Sharing the load -Thanks to the rate limiting set up in the [previous step](/terraform/tutorial/rate-limit), our login page is protected against credential brute force attacks. Now it's time to focus on performance and reliability. Imagine organic traffic has grown, and is increasingly global. It's time to spread these requests over multiple data centers. +Thanks to the rate limiting set up in the [previous step](/tutorial/rate-limit), our login page is protected against credential brute force attacks. Now it's time to focus on performance and reliability. Imagine organic traffic has grown, and is increasingly global. It's time to spread these requests over multiple data centers. In this tutorial step, we'll add a second origin for some basic round robining, and then use the [Cloudflare Load Balancing](https://www.cloudflare.com/load-balancing/) product to fail traffic over as needed. We'll then enhance our load balancing configuration through the use of "geo steering" to serve results from an origin server that is geographically closest to your end users. @@ -12,7 +13,7 @@ In this tutorial step, we'll add a second origin for some basic round robining, To get started, we'll add a DNS record for a second web server, which is located in Asia. The IP address for this server is 198.51.100.15. -``` +```sh $ git checkout -b step5-loadbalance Switched to a new branch 'step5-loadbalance' @@ -33,7 +34,7 @@ Note that while the name of the _resource_ is different as Terraform resources o Below we'll check the `terraform plan`, merge and apply the changes. -``` +```sh $ terraform plan | grep -v "" Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be @@ -86,7 +87,7 @@ Fast-forward Let's add the second DNS record for www.example.com: -``` +```sh $ terraform apply --auto-approve cloudflare_record.www: Refreshing state... (ID: c38d3103767284e7cd14d5dad3ab8668) cloudflare_zone_settings_override.example-com-settings: Refreshing state... (ID: e2e6491340be87a3726f91fc4148b126) @@ -111,7 +112,7 @@ Apply complete! Resources: 1 added, 0 changed, 0 destroyed. With the second DNS record in place, let's try making some requests to see where the traffic is served from: -``` +```sh $ for curl https://www.example.com Hello, this is 203.0.113.10! @@ -144,7 +145,7 @@ As described in the [load balancing tutorial](https://support.cloudflare.com/hc/ To monitor our origins we're going to create a basic health check that makes a GET request to each origin on the URL https://www.example.com. If the origin returns the `200/OK` status code within 5 seconds, we'll consider it healthy. If it fails to do so three (3) times in a row, we'll consider it unhealthy. This health check will be run once per minute from several regions, and send an email notification to you@example.com if any failures are detected. -``` +```sh $ git checkout step5-loadbalance Switched to branch 'step5-loadbalance' @@ -169,7 +170,7 @@ We will call our pool "www-servers" and add two origins to it: `www-us` (203.0.1 Note that we reference the monitor we added in the last step. When applying this confirmation, Terraform will figure out that it first needs to create the monitor so that it can look up the ID and provide to the pool we wish to create. -``` +```sh $ cat >> cloudflare.tf <<'EOF' resource "cloudflare_load_balancer_pool" "www-servers" { name = "www-servers" @@ -194,7 +195,7 @@ EOF Note that when you create a load balancer (LB), it will [replace any existing DNS records with the same name](https://support.cloudflare.com/hc/en-us/articles/115004954407-How-Does-a-Load-Balancer-Interact-with-Existing-DNS-Records-). For example, when we create the "www.example.com" LB below, it will supersede the two www DNS records that you have previously defined. One benefit of leaving this DNS records in place is that if you temporarily disable load balancing, connections to this hostname will still be possible as shown in Step #2 above. -``` +```sh $ cat >> cloudflare.tf <<'EOF' resource "cloudflare_load_balancer" "www-lb" { zone = "example.com" @@ -211,7 +212,7 @@ EOF As usual, we take a look at the proposed plan before we apply any changes: -``` +```sh $ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be @@ -296,7 +297,7 @@ can't guarantee that exactly these actions will be performed if The plan looks good so let's go ahead, merge it in, and apply it. -``` +```sh $ git add cloudflare.tf $ git commit -m "Step 5 - Create load balancer (LB) monitor, LB pool, and LB." [step5-loadbalance bc9aa9a] Step 5 - Create load balancer (LB) monitor, LB pool, and LB. @@ -367,7 +368,7 @@ Apply complete! Resources: 3 added, 0 changed, 0 destroyed. With load balancing in place, let's run those `curl` requests again to see where the traffic is served from: -``` +```sh $ for i in {1..4}; do curl https://www.example.com && sleep 5; done Hello, this is 198.51.100.15! @@ -378,4 +379,4 @@ Hello, this is 198.51.100.15! Hello, this is 203.0.113.10! ``` -Great, we're now seeing each request load balanced evenly across the two origins we defined. \ No newline at end of file +Great, we're now seeing each request load balanced evenly across the two origins we defined. diff --git a/products/terraform/src/content/tutorial/page-rules.md b/products/terraform/src/content/tutorial/page-rules.md index 51b056208d..18bf0f3b59 100644 --- a/products/terraform/src/content/tutorial/page-rules.md +++ b/products/terraform/src/content/tutorial/page-rules.md @@ -1,9 +1,11 @@ --- -title: Step 6 - Making some exceptions -weight: 60 +title: 6 – Making some exceptions +order: 6 --- -In [step 3](/terraform/tutorial/zone-settings) we configured zone settings that apply to all of example.com. In this step we're going to add an exception to these settings by using [Page Rules](https://www.cloudflare.com/features-page-rules/). +# Making some exceptions + +In [step 3](/tutorial/zone-settings) we configured zone settings that apply to all of example.com. In this step we're going to add an exception to these settings by using [Page Rules](https://www.cloudflare.com/features-page-rules/). Specifically, we're going to turn increase the security level for a URL we know is expensive to render (and cannot be cached): https://www.example.com/expensive-db-call. Additionally, we're going to add a redirect from the previous URL we used to host this page. @@ -11,7 +13,7 @@ Specifically, we're going to turn increase the security level for a URL we know As usual we'll create a new branch and append our configuration. -``` +```sh $ git checkout -b step6-pagerule Switched to a new branch 'step6-pagerule' @@ -44,7 +46,8 @@ EOF ## 2. Preview and merge the changes You know the drill: preview the changes Terraform is going to make and then merge them into the master branch. -``` + +```sh $ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be @@ -115,7 +118,7 @@ $ git commit -m "Step 6 - Add two Page Rules." $ git checkout master Switched to branch 'master' -$ git merge step6-pagerule +$ git merge step6-pagerule Updating 7a2ac34..d4fec16 Fast-forward cloudflare.tf | 23 +++++++++++++++++++++++ @@ -125,14 +128,15 @@ Fast-forward ## 3. Apply and verify the changes First we'll test requesting the (now missing) old location of the expensive-to-render page. -``` + +```sh $ curl -vso /dev/null https://www.example.com/old-location.php 2>&1 | grep "< HTTP\|Location" < HTTP/1.1 404 Not Found ``` As expected, it can't be found. Let's apply the Page Rules, including the redirect that should fix this error. -``` +```sh $ terraform apply --auto-approve cloudflare_record.www-asia: Refreshing state... (ID: fda39d8c9bf909132e82a36bab992864) cloudflare_load_balancer_monitor.get-root-https: Refreshing state... (ID: 4238142473fcd48e89ef1964be72e3e0) @@ -175,7 +179,7 @@ Apply complete! Resources: 2 added, 0 changed, 0 destroyed. With the Page Rules in place, let's try that call again, along with the I'm Under Attack Mode test: -``` +```sh $ curl -vso /dev/null https://www.example.com/old-location.php 2>&1 | grep "< HTTP\|Location" < HTTP/1.1 301 Moved Permanently < Location: https://www.upinatoms.com/expensive-db-call @@ -184,4 +188,4 @@ $ curl -vso /dev/null https://www.upinatoms.com/expensive-db-call 2>&1 | grep "< < HTTP/1.1 503 Service Temporarily Unavailable ``` -Great, they work as expected! In the first case the Cloudflare edge responds with a `301` redirecting the browser to the new location. In the second case it initially responds with a `503` (as is consistent with the "I Am Under Attack" mode). \ No newline at end of file +Great, they work as expected! In the first case the Cloudflare edge responds with a `301` redirecting the browser to the new location. In the second case it initially responds with a `503` (as is consistent with the "I Am Under Attack" mode). diff --git a/products/terraform/src/content/tutorial/rate-limit.md b/products/terraform/src/content/tutorial/rate-limit.md index b9c5358f73..46fbe22247 100644 --- a/products/terraform/src/content/tutorial/rate-limit.md +++ b/products/terraform/src/content/tutorial/rate-limit.md @@ -1,8 +1,10 @@ --- -title: Step 4 - Woah, slow down there -weight: 40 +title: 4 – Woah, slow down there +order: 4 --- +# Woah, slow down there + With our zone settings locked down, and our site starting to get some more attention, it's unfortunately begun attracting some of the less scrupulous characters on the internet. Our server access logs show attempts to brute force our login page at https://www.example.com/login. Let's see what we can do with Cloudflare's [rate limiting product](https://www.cloudflare.com/rate-limiting/) to put a stop to these efforts. ## 1. Create a new branch and append the rate limiting settings @@ -210,7 +212,7 @@ Error: Error applying plan: * cloudflare_rate_limit.login-limit: error creating rate limit for zone: error from makeRequest: HTTP status 400: content "{\n \"result\": null,\n \"success\": false,\n \"errors\": [\n {\n \"code\": 10021,\n \"message\": \"ratelimit.api.not_entitled.account\"\n }\n ],\n \"messages\": []\n}\n" ``` -## 3. Update the rule to ban (not just simulate) +## 3. Update the rule to ban (not just simulate) After confirming that the rule is triggering as planned in logs (but not yet enforcing), it's time to switch from `simulate` to `ban`: diff --git a/products/terraform/src/content/tutorial/roll-back.md b/products/terraform/src/content/tutorial/roll-back.md index f9ca1cc87d..2d7227d1ac 100644 --- a/products/terraform/src/content/tutorial/roll-back.md +++ b/products/terraform/src/content/tutorial/roll-back.md @@ -1,8 +1,10 @@ --- -title: Step 7 - On final thought, let’s roll some of that back -weight: 70 +title: 7 – On final thought... +order: 7 --- +# On final thought, let’s roll some of that back + We've come a long way! Now it's time to tear it all down. Well, maybe just part of it. Sometimes when you deploy configuration changes you later determine that they need to be rolled back. You could be performance testing a new configuration and want to revert to your previous configuration when done testing. Or maybe you fat-fingered an IP address and brought your entire site down (#hugops). @@ -12,7 +14,8 @@ Either way, if you've determined you want to revert your configuration, all you ## 1. Reviewing your configuration history Before we figure out how far back in time we want to rollback, let's take a look at our (git) versioned history. -``` + +```sh $ git log commit d4fec164581bec44684a4d59bb80aec1f1da5a6e Author: Me @@ -68,7 +71,8 @@ Another nice benefit of storing your Cloudflare configuration in git is that you ## 2. Examining specific historical changes To begin with, let's see what the last change we made was. -``` + +```sh $ git show commit d4fec164581bec44684a4d59bb80aec1f1da5a6e Author: Me @@ -110,10 +114,11 @@ index 0b39450..ef11d8a 100644 ``` Now let's look at the past few changes: -``` + +```sh $ git log -p -3 -... +... // page rule config from above ... @@ -190,14 +195,15 @@ index 9f25a0c..b92cb6f 100644 +} ``` - ## 3. Redeploying the previous configuration -Imagine that shortly after we deployed the Page Rules from [step 6](/terraform/tutorial/page-rules), we got a call from the Product team that manages this page: "The URL was only being used by one customer and is no longer needed, let's drop the security setting and redirect." + +Imagine that shortly after we deployed the Page Rules from [step 6](/tutorial/page-rules), we got a call from the Product team that manages this page: "The URL was only being used by one customer and is no longer needed, let's drop the security setting and redirect." While you could always edit the config file directly and delete those entries, it's easier to let `git` do it for us. To begin with, let's ask git to revert the last commit (without rewriting history). ### i. Revert the branch to the previous commit -``` + +```sh $ git revert HEAD~1..HEAD [master f9a6f7d] Revert "Step 6 - Bug fix." 1 file changed, 1 insertion(+), 1 deletion(-) @@ -208,7 +214,7 @@ Author: Me Date: Wed Apr 18 23:28:09 2018 -0700 Revert "Step 6 - Add two Page Rules." - + This reverts commit d4fec164581bec44684a4d59bb80aec1f1da5a6e. commit d4fec164581bec44684a4d59bb80aec1f1da5a6e @@ -222,7 +228,7 @@ Date: Wed Apr 18 22:04:52 2018 -0700 As expected, Terraform is indicating it will remove the two Page Rules we created in the previous step. -``` +```sh $ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be @@ -264,7 +270,7 @@ can't guarantee that exactly these actions will be performed if The changes look good, so let's ask Terraform to roll our Cloudflare configuration back. -``` +```sh $ terraform apply --auto-approve cloudflare_page_rule.redirect-to-new-db-page: Refreshing state... (ID: c5c40ff2dc12416b5fe4d0541980c591) cloudflare_page_rule.increase-security-on-expensive-page: Refreshing state... (ID: 1c13fdb84710c4cc8b11daf7ffcca449) @@ -283,4 +289,4 @@ cloudflare_page_rule.redirect-to-new-db-page: Destruction complete after 1s Apply complete! Resources: 0 added, 0 changed, 2 destroyed. ``` -Two resources destroyed, as expected. We've rolled back to the previous version. \ No newline at end of file +Two resources destroyed, as expected. We've rolled back to the previous version. diff --git a/products/terraform/src/content/tutorial/source-control.md b/products/terraform/src/content/tutorial/source-control.md index 482df93c11..1797b44ab8 100644 --- a/products/terraform/src/content/tutorial/source-control.md +++ b/products/terraform/src/content/tutorial/source-control.md @@ -1,12 +1,14 @@ --- -title: Step 2 - Tracking your history -weight: 20 +title: 2 – Tracking your history +order: 2 --- -In the [first step](/terraform/tutorial/hello-world) of the tutorial, you created and applied some basic Cloudflare configuration. Terraform was able to apply this configuration to your account because you provided your email address and API token at the top of the `cloudflare.tf` file: +# Tracking your history -``` -$ head -n4 cloudflare.tf +In the [first step](/tutorial/hello-world) of the tutorial, you created and applied some basic Cloudflare configuration. Terraform was able to apply this configuration to your account because you provided your email address and API token at the top of the `cloudflare.tf` file: + +```sh +$ head -n4 cloudflare.tf provider "cloudflare" { email = "you@example.com" token = "your-api-key" @@ -19,11 +21,11 @@ In this step of the tutorial, we’re going to store your configuration in GitHu As a good security practice we need to remove your Cloudflare credentials from anything that will be committed to a repository. The Cloudflare Terraform provider supports reading these values from the `CLOUDFLARE_EMAIL` and `CLOUDFLARE_TOKEN` environment variables, so all we need to do is: -``` +```sh $ sed -ie 's/^.*email =.*$/ # email pulled from $CLOUDFLARE_EMAIL/' cloudflare.tf $ sed -ie 's/^.*token =.*$/ # token pulled from $CLOUDFLARE_TOKEN/' cloudflare.tf -$ head -n4 cloudflare.tf +$ head -n4 cloudflare.tf provider "cloudflare" { # email pulled from $CLOUDFLARE_EMAIL # token pulled from $CLOUDFLARE_TOKEN @@ -37,7 +39,7 @@ Note that you need to leave the empty provider definition in the file, so that T After completing the above step, it's a good idea to make sure that you can still authenticate to Cloudflare. By running `terraform plan` we can get Terraform to pull the current state (which requires a valid email and API key): -``` +```sh $ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be @@ -60,7 +62,7 @@ Now that credentials have been removed, it's time to initialize a git repository First we'll create the GitHub repository to store the config. This can be done via the GitHub UI or with a simple API call: -``` +```sh $ export GITHUB_USER=your-github-user $ export GITHUB_TOKEN=your-github-token @@ -73,7 +75,7 @@ git@github.com:$GITHUB_USER/cf-config.git Now we'll initialize a git repository and make our first commit: -``` +```sh $ git init Initialized empty Git repository in /Users/username/cf-config/.git/ @@ -86,11 +88,11 @@ $ git commit -m "Step 2 - Initial commit with webserver definition." create mode 100644 cloudflare.tf ``` -An astute reader may have noticed that we did _not_ commit the `.terraform` directory nor did we commit the `terraform.tfstate` file. The former was not committed because this repository may be used on a different architecture, and the plugins contained in this directory are built for the system on which `terraform init` was run. The latter was not committed as i) it may eventually contain sensitive strings and ii) it is not a good way to keep state in sync, as explained in [Sharing State](/terraform/advanced-topics/sharing-state). +An astute reader may have noticed that we did _not_ commit the `.terraform` directory nor did we commit the `terraform.tfstate` file. The former was not committed because this repository may be used on a different architecture, and the plugins contained in this directory are built for the system on which `terraform init` was run. The latter was not committed as i) it may eventually contain sensitive strings and ii) it is not a good way to keep state in sync, as explained in [Sharing State](/advanced-topics/sharing-state). To prevent git from bugging us about these files, let's add them to a new .gitignore file, commit it, and push everything to GitHub: -``` +```sh $ cat > .gitignore <<'EOF' .terraform/ terraform.tfstate* @@ -111,4 +113,4 @@ Writing objects: 100% (6/6), 762 bytes | 0 bytes/s, done. Total 6 (delta 0), reused 0 (delta 0) To git@github.com:$GITHUB_USER/cf-config.git * [new branch] master -> master -``` \ No newline at end of file +``` diff --git a/products/terraform/src/content/tutorial/zone-settings.md b/products/terraform/src/content/tutorial/zone-settings.md index 1a780848af..f3e250dd5b 100644 --- a/products/terraform/src/content/tutorial/zone-settings.md +++ b/products/terraform/src/content/tutorial/zone-settings.md @@ -1,8 +1,10 @@ --- -title: Step 3 - HTTPS all the things -weight: 30 +title: 3 – HTTPS all the things +order: 3 --- +# HTTPS all the things + Now that you've got a basic website proxied through Cloudflare, it's time to use Terraform to adjust some of the settings on your zone. In this tutorial step we'll configure some optional HTTPS settings, and then push the updated configuration to GitHub for posterity. We'll use a new git branch for the changes, and then merge it into master before applying. On a team, you might consider using this step as an opportunity for others to review your change before merging and deploying it. Or you may integrate Terraform into your CI/CD system to perform tests automatically using another Cloudflare domain. @@ -11,7 +13,7 @@ We'll use a new git branch for the changes, and then merge it into master before Here we modify the Terraform configuration to enable the following settings: [TLS 1.3](https://www.cloudflare.com/learning-resources/tls-1-3/), [Always Use HTTPS](https://blog.cloudflare.com/how-to-make-your-site-https-only/), [Strict SSL mode](https://blog.cloudflare.com/introducing-strict-ssl-protecting-against-a-man-in-the-middle-attack-on-origin-traffic/), and the [Cloudflare WAF](https://www.cloudflare.com/waf/). Strict mode requires a valid SSL certificate on your origin, so be sure to use the [Cloudflare Origin CA](https://blog.cloudflare.com/cloudflare-ca-encryption-origin/) to generate one. -``` +```sh $ git checkout -b step3-https Switched to a new branch 'step3-https' @@ -34,7 +36,7 @@ EOF Let's take a look at what Terraform is proposing before we apply it. We filter the `terraform plan` output to ignore those values that will be "computed"—in this case, settings that will be left at their default values. -``` +```sh $ terraform plan | grep -v "" Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be @@ -70,7 +72,7 @@ can't guarantee that exactly these actions will be performed if The proposed changes look good, so we'll merge them into master and then apply them with `terraform apply`. When working on a team, you may want to require pull requests and use this opportunity to peer review any proposed configuration changes. -``` +```sh $ git add cloudflare.tf $ git commit -m "Step 3 - Enable TLS 1.3, Always Use HTTPS, and SSL Strict mode." [step3-https d540600] Step 3 - Enable TLS 1.3, Always Use HTTPS, and SSL Strict mode. @@ -98,9 +100,9 @@ To git@github.com:$GITHUB_USER/cf-config.git ## 3. Apply and verify the changes -Before applying the changes, let's see if we can connect with TLS 1.3. Hint: we shouldn't be able to with default settings. If you want to follow along with this test, you'll need to [compile curl against BoringSSL](https://ec.haxx.se/building-boringssl.html). +Before applying the changes, let's see if we can connect with TLS 1.3. Hint: we shouldn't be able to with default settings. If you want to follow along with this test, you'll need to [compile curl against BoringSSL](https://ec.haxx.se/building-boringssl.html). -``` +```sh $ curl -v --tlsv1.3 https://www.upinatoms.com 2>&1 | grep "SSL connection\|error" * error:1000042e:SSL routines:OPENSSL_internal:TLSV1_ALERT_PROTOCOL_VERSION curl: (35) error:1000042e:SSL routines:OPENSSL_internal:TLSV1_ALERT_PROTOCOL_VERSION @@ -108,7 +110,7 @@ curl: (35) error:1000042e:SSL routines:OPENSSL_internal:TLSV1_ALERT_PROTOCOL_VER As shown above, we receive an error as TLS 1.3 is not yet enabled on your zone. Let's enable it by running `terraform apply` and try again: -``` +```sh $ terraform apply --auto-approve cloudflare_record.www: Refreshing state... (ID: c38d3103767284e7cd14d5dad3ab8668) cloudflare_zone_settings_override.example-com-settings: Creating... @@ -168,7 +170,7 @@ Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Now we can try the same command as above, and see that it succeeds. Nice, TLS 1.3! -``` +```sh $ curl -v --tlsv1.3 https://www.example.com 2>&1 | grep "SSL connection\|error" * SSL connection using TLSv1.3 / AEAD-AES128-GCM-SHA256 ```