Skip to content

Commit

Permalink
Merge pull request #291 from opencredo/serviced-waf-implementation
Browse files Browse the repository at this point in the history
Add WAF support
  • Loading branch information
phamann authored Aug 10, 2020
2 parents d115b6d + c61ef0e commit d3541e6
Show file tree
Hide file tree
Showing 51 changed files with 9,194 additions and 897 deletions.
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

0 comments on commit d3541e6

Please sign in to comment.