Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WAF support #291

Merged
merged 26 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
904fc04
Service waf component (#9)
oscarDovao Nov 26, 2019
1843373
correcting casing
oscarDovao Nov 26, 2019
3095c17
fixing casing
oscarDovao Nov 27, 2019
537b032
Waf configuration resource (#12)
oscarDovao Nov 29, 2019
70ece20
Waf active rules (#15)
oscarDovao Dec 12, 2019
5bfb858
Waf rules (#14)
oscarDovao Jan 8, 2020
e723304
Implementing WAF configuration resource deletion (#18)
oscarDovao Jan 8, 2020
0247449
Waf disable enable (#20)
oscarDovao Jan 8, 2020
fb49b06
Using the batch size constant specific for WAF
oscarDovao Dec 20, 2019
3ee3087
Waf resource import (#23)
oscarDovao Jan 23, 2020
1d9d937
Terraform conventions (#28)
oscarDovao Jan 23, 2020
b663bc6
Waf documentation (#27)
oscarDovao Jan 23, 2020
6f405dc
Active rules post update (#29)
oscarDovao Jan 27, 2020
43118d3
WAF documentation enhancements (#30)
oscarDovao Jan 27, 2020
1d571a9
Migrate WAF to new-style blocks
yoink00 Jun 30, 2020
a78dadc
Update enable/disable WAF API and add test for created disabled
yoink00 Jul 1, 2020
7e81bd6
Remove `disabled` field from service's WAF block
yoink00 Jul 10, 2020
182c38f
Merge pull request #1 from fastly/WAF-1748-unrequire-prefetch-condition
squeemishly Apr 21, 2020
9163728
Update WAF to use new vclAttribute pattern
yoink00 Jul 21, 2020
cfdf34c
Update module vendoring
yoink00 Jul 21, 2020
22962cc
Deal with async deployments
yoink00 Jul 3, 2020
0ded69b
Mark WAF Configuration items computed to fix import issues
yoink00 Jul 6, 2020
e7c8f98
Add plan-only test for WAF Configuration import
yoink00 Jul 6, 2020
5f5a4e8
Dependencies: point go-fastly to the v2.0.0 working branch.
phamann Aug 7, 2020
d21164a
Refactor WAF documentation to use new templating pattern.
phamann Aug 7, 2020
c61ef0e
Rename fastly_service_waf_configuration_v1 to fastly_service_waf_conf…
phamann Aug 7, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,16 @@ jobs:
uses: actions/checkout@v2
with:
path: go/src/github.com/${{ github.repository }}
- name: Restore cache
uses: actions/cache@v2
- name: Checkout code
uses: actions/checkout@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-mod-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-mod-
repository: 'hashicorp/terraform-website'
path: go/src/github.com/hashicorp/terraform-website
- name: Run website-test
run: |
cd $GOPATH/src/github.com/${{ github.repository }}
ln -sf ../../../../ext/providers/fastly/website/docs $GOPATH/src/github.com/hashicorp/terraform-website/content/source/docs/providers/fastly
ln -sf ../../../../ext/providers/fastly/website/fastly.erb $GOPATH/src/github.com/hashicorp/terraform-website/content/source/layouts/fastly.erb
make website-test
- name: Check diff
run: |
Expand Down
4 changes: 2 additions & 2 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ TEST?=$$(go list ./... |grep -v 'vendor')
GOFMT_FILES?=$$(find . -name '*.go' |grep -v vendor)
WEBSITE_REPO=github.com/hashicorp/terraform-website
PKG_NAME=fastly
FULL_PKG_NAME=github.com/terraform-providers/terraform-provider-fastly
FULL_PKG_NAME=github.com/fastly/terraform-provider-fastly
VERSION_PLACEHOLDER=version.ProviderVersion
VERSION=$(shell git describe --tags --always)

Expand Down Expand Up @@ -59,7 +59,7 @@ ifeq (,$(wildcard $(GOPATH)/src/$(WEBSITE_REPO)))
echo "$(WEBSITE_REPO) not found in your GOPATH (necessary for layouts and assets), get-ting..."
git clone https://$(WEBSITE_REPO) $(GOPATH)/src/$(WEBSITE_REPO)
endif
go run scripts/website/parse-templates.go
go run "scripts/website/parse-templates.go"
@$(MAKE) -C $(GOPATH)/src/$(WEBSITE_REPO) website-provider-test PROVIDER_PATH=$(shell pwd) PROVIDER_NAME=$(PKG_NAME)

.PHONY: build test testacc vet fmt fmtcheck errcheck test-compile website website-test
Expand Down
180 changes: 180 additions & 0 deletions fastly/block_fastly_service_v1_waf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package fastly

import (
"fmt"
"log"
"strconv"

gofastly "github.com/fastly/go-fastly/fastly"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

type WAFServiceAttributeHandler struct {
*DefaultServiceAttributeHandler
}

func NewServiceWAF(sa ServiceMetadata) ServiceAttributeDefinition {
return &WAFServiceAttributeHandler{
&DefaultServiceAttributeHandler{
key: "waf",
serviceMetadata: sa,
},
}
}

func (h *WAFServiceAttributeHandler) Register(s *schema.Resource) error {
s.Schema[h.GetKey()] = &schema.Schema{
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"response_object": {
Type: schema.TypeString,
Required: true,
Description: "The Web Application Firewall's (WAF) response object",
},
"prefetch_condition": {
Type: schema.TypeString,
Optional: true,
Description: "The Web Application Firewall's (WAF) prefetch condition",
},
"waf_id": {
Type: schema.TypeString,
Computed: true,
Description: "The Web Application Firewall (WAF) ID",
},
},
},
}

return nil
}

func (h *WAFServiceAttributeHandler) Process(d *schema.ResourceData, latestVersion int, conn *gofastly.Client) error {
serviceID := d.Id()
serviceVersion := strconv.Itoa(latestVersion)
oldWAFVal, newWAFVal := d.GetChange(h.GetKey())

if len(newWAFVal.([]interface{})) > 0 {
wf := newWAFVal.([]interface{})[0].(map[string]interface{})

var err error
if wafExists(conn, serviceID, serviceVersion, wf["waf_id"].(string)) {
opts := buildUpdateWAF(wf, serviceID, serviceVersion)
log.Printf("[DEBUG] Fastly WAF update opts: %#v", opts)
_, err = conn.UpdateWAF(opts)
} else {
opts := buildCreateWAF(wf, serviceID, serviceVersion)
log.Printf("[DEBUG] Fastly WAF Addition opts: %#v", opts)

_, err = conn.CreateWAF(opts)
}
if err != nil {
return err
}
} else if len(oldWAFVal.([]interface{})) > 0 {

wf := oldWAFVal.([]interface{})[0].(map[string]interface{})

opts := buildDeleteWAF(wf, serviceVersion)
log.Printf("[DEBUG] Fastly WAF Removal opts: %#v", opts)
err := conn.DeleteWAF(opts)
if errRes, ok := err.(*gofastly.HTTPError); ok {
if errRes.StatusCode != 404 {
return err
}
} else if err != nil {
return err
}
}
return nil
}

func (h *WAFServiceAttributeHandler) Read(d *schema.ResourceData, s *gofastly.ServiceDetail, conn *gofastly.Client) error {
// refresh WAFs
log.Printf("[DEBUG] Refreshing WAFs for (%s)", d.Id())
wafList, err := conn.ListWAFs(&gofastly.ListWAFsInput{
FilterService: d.Id(),
FilterVersion: s.ActiveVersion.Number,
})
if err != nil {
return fmt.Errorf("[ERR] Error looking up WAFs for (%s), version (%v): %s", d.Id(), s.ActiveVersion.Number, err)
}

waf := flattenWAFs(wafList.Items)

if err := d.Set("waf", waf); err != nil {
log.Printf("[WARN] Error setting waf for (%s): %s", d.Id(), err)
}
return nil
}

func wafExists(conn *gofastly.Client, s, v, id string) bool {

_, err := conn.GetWAF(&gofastly.GetWAFInput{
Service: s,
Version: v,
ID: id,
})
if err != nil {
return false
}
return true
}

func flattenWAFs(wafList []*gofastly.WAF) []map[string]interface{} {

var wl []map[string]interface{}
if len(wafList) == 0 {
return wl
}

w := wafList[0]
WAFMapString := map[string]interface{}{
"waf_id": w.ID,
"response_object": w.Response,
"prefetch_condition": w.PrefetchCondition,
}

// prune any empty values that come from the default string value in structs
for k, v := range WAFMapString {
if v == "" {
delete(WAFMapString, k)
}
}
return append(wl, WAFMapString)
}

func buildCreateWAF(WAFMap interface{}, serviceID string, ServiceVersion string) *gofastly.CreateWAFInput {
df := WAFMap.(map[string]interface{})
opts := gofastly.CreateWAFInput{
Service: serviceID,
Version: ServiceVersion,
ID: df["waf_id"].(string),
PrefetchCondition: df["prefetch_condition"].(string),
Response: df["response_object"].(string),
}
return &opts
}

func buildDeleteWAF(WAFMap interface{}, ServiceVersion string) *gofastly.DeleteWAFInput {
df := WAFMap.(map[string]interface{})
opts := gofastly.DeleteWAFInput{
ID: df["waf_id"].(string),
Version: ServiceVersion,
}
return &opts
}

func buildUpdateWAF(wafMap interface{}, serviceID string, ServiceVersion string) *gofastly.UpdateWAFInput {
df := wafMap.(map[string]interface{})
opts := gofastly.UpdateWAFInput{
Service: serviceID,
Version: ServiceVersion,
ID: df["waf_id"].(string),
PrefetchCondition: df["prefetch_condition"].(string),
Response: df["response_object"].(string),
}
return &opts
}
Loading