github.com/fastly/go-fastly@v1.18.0/fastly/waf_test.go (about)

     1  package fastly
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"testing"
     7  )
     8  
     9  func TestClient_WAFs(t *testing.T) {
    10  	t.Parallel()
    11  
    12  	var err error
    13  	var tv *Version
    14  	record(t, "wafs/version", func(c *Client) {
    15  		tv = testVersion(t, c)
    16  	})
    17  
    18  	// Enable logging on the service - we cannot create wafs without logging
    19  	// enabled
    20  	record(t, "wafs/logging/create", func(c *Client) {
    21  		_, err = c.CreateSyslog(&CreateSyslogInput{
    22  			Service:       testServiceID,
    23  			Version:       tv.Number,
    24  			Name:          "test-syslog",
    25  			Address:       "example.com",
    26  			Hostname:      "example.com",
    27  			Port:          1234,
    28  			Token:         "abcd1234",
    29  			Format:        "format",
    30  			FormatVersion: 2,
    31  			MessageType:   "classic",
    32  		})
    33  	})
    34  	if err != nil {
    35  		t.Fatal(err)
    36  	}
    37  	defer func() {
    38  		record(t, "wafs/logging/cleanup", func(c *Client) {
    39  			c.DeleteSyslog(&DeleteSyslogInput{
    40  				Service: testServiceID,
    41  				Version: tv.Number,
    42  				Name:    "test-syslog",
    43  			})
    44  		})
    45  	}()
    46  
    47  	// Create a condition - we cannot create a waf without attaching a condition
    48  	var condition *Condition
    49  	record(t, "wafs/condition/create", func(c *Client) {
    50  		condition, err = c.CreateCondition(&CreateConditionInput{
    51  			Service:   testServiceID,
    52  			Version:   tv.Number,
    53  			Name:      "test-waf-condition",
    54  			Statement: "req.url~+\"index.html\"",
    55  			Type:      "PREFETCH", // This must be a prefetch condition
    56  			Priority:  1,
    57  		})
    58  	})
    59  	if err != nil {
    60  		t.Fatal(err)
    61  	}
    62  	defer func() {
    63  		record(t, "wafs/condition/cleanup", func(c *Client) {
    64  			c.DeleteCondition(&DeleteConditionInput{
    65  				Service: testServiceID,
    66  				Version: tv.Number,
    67  				Name:    "test-waf-condition",
    68  			})
    69  		})
    70  	}()
    71  
    72  	// Create a response object
    73  	var ro *ResponseObject
    74  	record(t, "wafs/response_object/create", func(c *Client) {
    75  		ro, err = c.CreateResponseObject(&CreateResponseObjectInput{
    76  			Service:     testServiceID,
    77  			Version:     tv.Number,
    78  			Name:        "test-response-object",
    79  			Status:      200,
    80  			Response:    "Ok",
    81  			Content:     "abcd",
    82  			ContentType: "text/plain",
    83  		})
    84  	})
    85  	if err != nil {
    86  		t.Fatal(err)
    87  	}
    88  	defer func() {
    89  		record(t, "wafs/response_object/cleanup", func(c *Client) {
    90  			c.DeleteResponseObject(&DeleteResponseObjectInput{
    91  				Service: testServiceID,
    92  				Version: tv.Number,
    93  				Name:    ro.Name,
    94  			})
    95  		})
    96  	}()
    97  
    98  	// Create
    99  	var waf *WAF
   100  	record(t, "wafs/create", func(c *Client) {
   101  		waf, err = c.CreateWAF(&CreateWAFInput{
   102  			Service:           testServiceID,
   103  			Version:           tv.Number,
   104  			PrefetchCondition: condition.Name,
   105  			Response:          ro.Name,
   106  		})
   107  	})
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  
   112  	// List
   113  	var wafs []*WAF
   114  	record(t, "wafs/list", func(c *Client) {
   115  		wafs, err = c.ListWAFs(&ListWAFsInput{
   116  			Service: testServiceID,
   117  			Version: tv.Number,
   118  		})
   119  	})
   120  	if err != nil {
   121  		t.Fatal(err)
   122  	}
   123  	if len(wafs) < 1 {
   124  		t.Errorf("bad wafs: %v", wafs)
   125  	}
   126  
   127  	// Ensure deleted
   128  	defer func() {
   129  		record(t, "wafs/cleanup", func(c *Client) {
   130  			c.DeleteWAF(&DeleteWAFInput{
   131  				Service: testServiceID,
   132  				Version: tv.Number,
   133  				ID:      waf.ID,
   134  			})
   135  		})
   136  	}()
   137  
   138  	// Get
   139  	var nwaf *WAF
   140  	record(t, "wafs/get", func(c *Client) {
   141  		nwaf, err = c.GetWAF(&GetWAFInput{
   142  			Service: testServiceID,
   143  			Version: tv.Number,
   144  			ID:      waf.ID,
   145  		})
   146  	})
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  	if nwaf.ID != waf.ID {
   151  		t.Errorf("expected %q to be %q", nwaf.ID, waf.ID)
   152  	}
   153  
   154  	// Get the WAF ruleset
   155  	var ruleset *Ruleset
   156  	record(t, "wafs/ruleset/get", func(c *Client) {
   157  		ruleset, err = c.GetWAFRuleRuleSets(&GetWAFRuleRuleSetsInput{
   158  			Service: testServiceID,
   159  			ID:      waf.ID,
   160  		})
   161  	})
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  	if ruleset.ID != waf.ID {
   166  		t.Errorf("expected %q to be %q", ruleset.ID, waf.ID)
   167  	}
   168  	if ruleset.VCL == "" {
   169  		t.Error("bad vcl")
   170  	}
   171  	if ruleset.LastPush != waf.LastPush {
   172  		t.Errorf("expected %q to be %q", ruleset.LastPush, waf.LastPush)
   173  	}
   174  	if ruleset.Link != "" {
   175  		t.Error("bad link")
   176  	}
   177  
   178  	// Update
   179  	// Create a new response object to attach
   180  	var nro *ResponseObject
   181  	record(t, "wafs/response_object/create_another", func(c *Client) {
   182  		nro, err = c.CreateResponseObject(&CreateResponseObjectInput{
   183  			Service:     testServiceID,
   184  			Version:     tv.Number,
   185  			Name:        "test-response-object-2",
   186  			Status:      200,
   187  			Response:    "Ok",
   188  			Content:     "efgh",
   189  			ContentType: "text/plain",
   190  		})
   191  	})
   192  	if err != nil {
   193  		t.Fatal(err)
   194  	}
   195  	defer func() {
   196  		record(t, "wafs/response_object/cleanup_another", func(c *Client) {
   197  			c.DeleteResponseObject(&DeleteResponseObjectInput{
   198  				Service: testServiceID,
   199  				Version: tv.Number,
   200  				Name:    nro.Name,
   201  			})
   202  		})
   203  	}()
   204  	var uwaf *WAF
   205  	record(t, "wafs/update", func(c *Client) {
   206  		uwaf, err = c.UpdateWAF(&UpdateWAFInput{
   207  			Service:  testServiceID,
   208  			Version:  tv.Number,
   209  			ID:       waf.ID,
   210  			Response: nro.Name,
   211  		})
   212  	})
   213  	if err != nil {
   214  		t.Fatal(err)
   215  	}
   216  	if uwaf.Response != "test-response-object-2" {
   217  		t.Errorf("bad name: %q", uwaf.Response)
   218  	}
   219  
   220  	// Update the WAF ruleset
   221  	var uRuleset *Ruleset
   222  	record(t, "wafs/ruleset/patch", func(c *Client) {
   223  		uRuleset, err = c.UpdateWAFRuleSets(&UpdateWAFRuleRuleSetsInput{
   224  			Service: testServiceID,
   225  			ID:      uwaf.ID,
   226  		})
   227  	})
   228  	if err != nil {
   229  		t.Fatal(err)
   230  	}
   231  	if uRuleset.ID != uwaf.ID {
   232  		t.Errorf("expected %q to be %q", uRuleset.ID, uwaf.ID)
   233  	}
   234  	if uRuleset.VCL != "" {
   235  		t.Error("bad vcl")
   236  	}
   237  	if uRuleset.LastPush != nil {
   238  		t.Error("bad last_push")
   239  	}
   240  	if uRuleset.Link == "" {
   241  		t.Error("bad link")
   242  	}
   243  
   244  	// Delete
   245  	record(t, "wafs/delete", func(c *Client) {
   246  		err = c.DeleteWAF(&DeleteWAFInput{
   247  			Service: testServiceID,
   248  			Version: tv.Number,
   249  			ID:      waf.ID,
   250  		})
   251  	})
   252  	if err != nil {
   253  		t.Fatal(err)
   254  	}
   255  
   256  }
   257  
   258  func TestClient_ListWAFs_validation(t *testing.T) {
   259  	var err error
   260  	_, err = testClient.ListWAFs(&ListWAFsInput{
   261  		Service: "",
   262  	})
   263  	if err != ErrMissingService {
   264  		t.Errorf("bad error: %s", err)
   265  	}
   266  
   267  	_, err = testClient.ListWAFs(&ListWAFsInput{
   268  		Service: "foo",
   269  		Version: 0,
   270  	})
   271  	if err != ErrMissingVersion {
   272  		t.Errorf("bad error: %s", err)
   273  	}
   274  }
   275  
   276  func TestClient_CreateWAF_validation(t *testing.T) {
   277  	var err error
   278  	_, err = testClient.CreateWAF(&CreateWAFInput{
   279  		Service: "",
   280  	})
   281  	if err != ErrMissingService {
   282  		t.Errorf("bad error: %s", err)
   283  	}
   284  
   285  	_, err = testClient.CreateWAF(&CreateWAFInput{
   286  		Service: "foo",
   287  		Version: 0,
   288  	})
   289  	if err != ErrMissingVersion {
   290  		t.Errorf("bad error: %s", err)
   291  	}
   292  }
   293  
   294  func TestClient_GetWAF_validation(t *testing.T) {
   295  	var err error
   296  	_, err = testClient.GetWAF(&GetWAFInput{
   297  		Service: "",
   298  	})
   299  	if err != ErrMissingService {
   300  		t.Errorf("bad error: %s", err)
   301  	}
   302  
   303  	_, err = testClient.GetWAF(&GetWAFInput{
   304  		Service: "foo",
   305  		Version: 0,
   306  	})
   307  	if err != ErrMissingVersion {
   308  		t.Errorf("bad error: %s", err)
   309  	}
   310  
   311  	_, err = testClient.GetWAF(&GetWAFInput{
   312  		Service: "foo",
   313  		Version: 1,
   314  		ID:      "",
   315  	})
   316  	if err != ErrMissingWAFID {
   317  		t.Errorf("bad error: %s", err)
   318  	}
   319  }
   320  
   321  //
   322  // func TestClient_UpdateWAF_validation(t *testing.T) {
   323  // 	var err error
   324  // 	_, err = testClient.UpdateWAF(&UpdateWAFInput{
   325  // 		Service: "",
   326  // 	})
   327  // 	if err != ErrMissingService {
   328  // 		t.Errorf("bad error: %s", err)
   329  // 	}
   330  //
   331  // 	_, err = testClient.UpdateWAF(&UpdateWAFInput{
   332  // 		Service: "foo",
   333  // 		Version: 0,
   334  // 	})
   335  // 	if err != ErrMissingVersion {
   336  // 		t.Errorf("bad error: %s", err)
   337  // 	}
   338  //
   339  // 	_, err = testClient.UpdateWAF(&UpdateWAFInput{
   340  // 		Service: "foo",
   341  // 		Version: 1,
   342  // 		WAFID:   "",
   343  // 	})
   344  // 	if err != ErrMissingWAFID {
   345  // 		t.Errorf("bad error: %s", err)
   346  // 	}
   347  // }
   348  //
   349  // func TestClient_DeleteWAF_validation(t *testing.T) {
   350  // 	var err error
   351  // 	err = testClient.DeleteWAF(&DeleteWAFInput{
   352  // 		Service: "",
   353  // 	})
   354  // 	if err != ErrMissingService {
   355  // 		t.Errorf("bad error: %s", err)
   356  // 	}
   357  //
   358  // 	err = testClient.DeleteWAF(&DeleteWAFInput{
   359  // 		Service: "foo",
   360  // 		Version: 0,
   361  // 	})
   362  // 	if err != ErrMissingVersion {
   363  // 		t.Errorf("bad error: %s", err)
   364  // 	}
   365  //
   366  // 	err = testClient.DeleteWAF(&DeleteWAFInput{
   367  // 		Service: "foo",
   368  // 		Version: 1,
   369  // 		WAFID:   "",
   370  // 	})
   371  // 	if err != ErrMissingWAFID {
   372  // 		t.Errorf("bad error: %s", err)
   373  // 	}
   374  // }
   375  
   376  func TestUpdateWAFRuleStatusesInput_validate(t *testing.T) {
   377  	tests := []struct {
   378  		description string
   379  		input       UpdateWAFRuleStatusInput
   380  		expected    error
   381  	}{
   382  		{
   383  			description: "Accepts valid input",
   384  			input: UpdateWAFRuleStatusInput{
   385  				ID:      "as098k-8104",
   386  				RuleID:  8104,
   387  				Service: "108asj1",
   388  				WAF:     "as098k",
   389  				Status:  "block",
   390  			},
   391  			expected: nil,
   392  		},
   393  		{
   394  			description: "Rejects input with missing int field",
   395  			input: UpdateWAFRuleStatusInput{
   396  				ID:      "as098k-8104",
   397  				Service: "108asj1",
   398  				WAF:     "as098k",
   399  				Status:  "block",
   400  			},
   401  			expected: ErrMissingRuleID,
   402  		},
   403  		{
   404  			description: "Rejects input with missing string field",
   405  			input: UpdateWAFRuleStatusInput{
   406  				ID:     "as098k-8104",
   407  				RuleID: 8104,
   408  				WAF:    "as098k",
   409  				Status: "block",
   410  			},
   411  			expected: ErrMissingService,
   412  		},
   413  	}
   414  	for _, testcase := range tests {
   415  		err := testcase.input.validate()
   416  		if err != testcase.expected {
   417  			t.Errorf("In test %s: Expected %v,got %v", testcase.description, testcase.expected, err)
   418  		}
   419  	}
   420  }
   421  
   422  func TestUpdateWAFRuleTagStatusInput_validate(t *testing.T) {
   423  	tests := []struct {
   424  		description string
   425  		input       UpdateWAFRuleTagStatusInput
   426  		expected    error
   427  	}{
   428  		{
   429  			description: "Accepts valid input",
   430  			input: UpdateWAFRuleTagStatusInput{
   431  				Tag:     "lala tag la",
   432  				Service: "108asj1",
   433  				WAF:     "as098k",
   434  				Status:  "block",
   435  			},
   436  			expected: nil,
   437  		},
   438  		{
   439  			description: "Rejects input with missing string field",
   440  			input: UpdateWAFRuleTagStatusInput{
   441  				Service: "108asj1",
   442  				WAF:     "as098k",
   443  				Status:  "block",
   444  			},
   445  			expected: ErrMissingTag,
   446  		},
   447  	}
   448  	for _, testcase := range tests {
   449  		err := testcase.input.validate()
   450  		if err != testcase.expected {
   451  			t.Errorf("In test %s: Expected %v,got %v", testcase.description, testcase.expected, err)
   452  		}
   453  	}
   454  }
   455  
   456  func TestGetWAFRuleStatusesInput_formatFilters(t *testing.T) {
   457  	tests := []struct {
   458  		description string
   459  		filters     GetWAFRuleStatusesFilters
   460  		expected    map[string]string
   461  	}{
   462  		{
   463  			description: "converts both strings and ints to strings",
   464  			filters: GetWAFRuleStatusesFilters{
   465  				Status:   "log",
   466  				Accuracy: 10,
   467  				Version:  "180ad",
   468  			},
   469  			expected: map[string]string{
   470  				"filter[status]":         "log",
   471  				"filter[rule][accuracy]": "10",
   472  				"filter[rule][version]":  "180ad",
   473  			},
   474  		},
   475  		{
   476  			description: "converts arrays to strings",
   477  			filters: GetWAFRuleStatusesFilters{
   478  				Status:  "log",
   479  				Version: "181ad",
   480  				Tags:    []int{18, 1, 1093, 86308},
   481  			},
   482  			expected: map[string]string{
   483  				"filter[status]":        "log",
   484  				"filter[rule][version]": "181ad",
   485  				"include":               "18,1,1093,86308",
   486  			},
   487  		},
   488  	}
   489  	for _, testcase := range tests {
   490  		input := GetWAFRuleStatusesInput{
   491  			Filters: testcase.filters,
   492  		}
   493  		answer := input.formatFilters()
   494  		if len(answer) != len(testcase.expected) {
   495  			t.Errorf("In test %s: Expected map with %d entries,got one with %d", testcase.description, len(testcase.expected), len(answer))
   496  		}
   497  		for key, value := range testcase.expected {
   498  			if answer[key] != value {
   499  				t.Errorf("In test %s: Expected %s key to have value %s, got %s", testcase.description, key, value, answer[key])
   500  			}
   501  		}
   502  	}
   503  }
   504  
   505  func TestGetPages(t *testing.T) {
   506  	tests := []struct {
   507  		description   string
   508  		input         string
   509  		expectedPages paginationInfo
   510  		expectedErr   error
   511  	}{
   512  		{
   513  			description: "returns the next page",
   514  			input:       `{"links": {"next": "https://google.com/2"}, "data": []}`,
   515  			expectedPages: paginationInfo{
   516  				Next: "https://google.com/2",
   517  			},
   518  		},
   519  		{
   520  			description: "returns multiple pages",
   521  			input:       `{"links": {"next": "https://google.com/2", "first": "https://google.com/1"}, "data": []}`,
   522  			expectedPages: paginationInfo{
   523  				First: "https://google.com/1",
   524  				Next:  "https://google.com/2",
   525  			},
   526  		},
   527  		{
   528  			description:   "returns no pages",
   529  			input:         `{"data": []}`,
   530  			expectedPages: paginationInfo{},
   531  		},
   532  	}
   533  	for _, testcase := range tests {
   534  		pages, reader, err := getPages(bytes.NewReader([]byte(testcase.input)))
   535  		if pages != testcase.expectedPages {
   536  			t.Errorf("Test %s: Expected pages %+v, got %+v", testcase.description, testcase.expectedPages, pages)
   537  		}
   538  
   539  		// we expect to be able to get the original input out again
   540  		resultBytes, _ := ioutil.ReadAll(reader)
   541  		if string(resultBytes) != testcase.input {
   542  			t.Errorf("Test %s: Expected body %s, got %s", testcase.description, testcase.input, string(resultBytes))
   543  		}
   544  		if err != testcase.expectedErr {
   545  			t.Errorf("Test %s: Expected error %v, got %v", testcase.description, testcase.expectedErr, err)
   546  		}
   547  	}
   548  }
   549  
   550  func TestUpdateWAFConfigSetInput_validate(t *testing.T) {
   551  	tests := []struct {
   552  		description string
   553  		input       UpdateWAFConfigSetInput
   554  		expected    error
   555  	}{
   556  		{
   557  			description: "Accepts valid input",
   558  			input: UpdateWAFConfigSetInput{
   559  				WAFList:     []ConfigSetWAFs{{ID: "derpID"}},
   560  				ConfigSetID: "derpConfigSet",
   561  			},
   562  			expected: nil,
   563  		},
   564  	}
   565  	for _, testcase := range tests {
   566  		err := testcase.input.validate()
   567  		if err != testcase.expected {
   568  			t.Errorf("In test %s: Expected %v,got %v", testcase.description, testcase.expected, err)
   569  		}
   570  	}
   571  }