k8s.io/apiserver@v0.31.1/pkg/audit/policy/reader_test.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package policy
    18  
    19  import (
    20  	"io/ioutil"
    21  	"os"
    22  	"reflect"
    23  	"strings"
    24  	"testing"
    25  
    26  	"k8s.io/apiserver/pkg/apis/audit"
    27  
    28  	// import to call webhook's init() function to register audit.Policy to schema
    29  	_ "k8s.io/apiserver/plugin/pkg/audit/webhook"
    30  
    31  	"github.com/google/go-cmp/cmp"
    32  	"github.com/stretchr/testify/assert"
    33  	"github.com/stretchr/testify/require"
    34  )
    35  
    36  const policyDefPattern = `
    37  apiVersion: audit.k8s.io/{version}
    38  kind: Policy
    39  rules:
    40    - level: None
    41      nonResourceURLs:
    42        - /healthz*
    43        - /version
    44    - level: RequestResponse
    45      users: ["tim"]
    46      userGroups: ["testers", "developers"]
    47      verbs: ["patch", "delete", "create"]
    48      resources:
    49        - group: ""
    50        - group: "rbac.authorization.k8s.io"
    51          resources: ["clusterroles", "clusterrolebindings"]
    52      namespaces: ["default", "kube-system"]
    53    - level: Metadata
    54  `
    55  
    56  const policyWithNoVersionOrKind = `
    57  rules:
    58    - level: None
    59      nonResourceURLs:
    60        - /healthz*
    61        - /version
    62    - level: RequestResponse
    63      users: ["tim"]
    64      userGroups: ["testers", "developers"]
    65      verbs: ["patch", "delete", "create"]
    66      resources:
    67        - group: ""
    68        - group: "rbac.authorization.k8s.io"
    69          resources: ["clusterroles", "clusterrolebindings"]
    70      namespaces: ["default", "kube-system"]
    71    - level: Metadata
    72  `
    73  
    74  const policyWithUnknownField = `
    75  apiVersion: audit.k8s.io/v1
    76  kind: Policy
    77  rules:
    78  - level: None
    79    resources:
    80    - group: coordination.k8s.io
    81      resources:
    82      - "leases"
    83      verbs: ["watch", "get", "list"] # invalid indentation on verbs
    84  `
    85  
    86  var expectedPolicy = &audit.Policy{
    87  	Rules: []audit.PolicyRule{{
    88  		Level:           audit.LevelNone,
    89  		NonResourceURLs: []string{"/healthz*", "/version"},
    90  	}, {
    91  		Level:      audit.LevelRequestResponse,
    92  		Users:      []string{"tim"},
    93  		UserGroups: []string{"testers", "developers"},
    94  		Verbs:      []string{"patch", "delete", "create"},
    95  		Resources: []audit.GroupResources{{}, {
    96  			Group:     "rbac.authorization.k8s.io",
    97  			Resources: []string{"clusterroles", "clusterrolebindings"},
    98  		}},
    99  		Namespaces: []string{"default", "kube-system"},
   100  	}, {
   101  		Level: audit.LevelMetadata,
   102  	}},
   103  }
   104  
   105  func TestParser(t *testing.T) {
   106  	policyDef := strings.Replace(policyDefPattern, "{version}", "v1", 1)
   107  	f, err := writePolicy(t, policyDef)
   108  	require.NoError(t, err)
   109  	defer os.Remove(f)
   110  
   111  	policy, err := LoadPolicyFromFile(f)
   112  	require.NoError(t, err)
   113  
   114  	assert.Len(t, policy.Rules, 3) // Sanity check.
   115  	if !reflect.DeepEqual(policy, expectedPolicy) {
   116  		t.Errorf("Unexpected policy! Diff:\n%s", cmp.Diff(policy, expectedPolicy))
   117  	}
   118  }
   119  
   120  func TestParsePolicyWithNoVersionOrKind(t *testing.T) {
   121  	f, err := writePolicy(t, policyWithNoVersionOrKind)
   122  	require.NoError(t, err)
   123  	defer os.Remove(f)
   124  
   125  	_, err = LoadPolicyFromFile(f)
   126  	assert.Contains(t, err.Error(), "unknown group version field")
   127  }
   128  
   129  func TestParsePolicyWithUnknownField(t *testing.T) {
   130  	f, err := writePolicy(t, policyWithUnknownField)
   131  	require.NoError(t, err)
   132  	defer os.Remove(f)
   133  
   134  	_, err = LoadPolicyFromFile(f)
   135  	require.NoError(t, err)
   136  }
   137  
   138  func TestPolicyCntCheck(t *testing.T) {
   139  	var testCases = []struct {
   140  		caseName, policy string
   141  	}{
   142  		{
   143  			"policyWithNoRule",
   144  			`apiVersion: audit.k8s.io/v1
   145  kind: Policy`,
   146  		},
   147  		{"emptyPolicyFile", ""},
   148  	}
   149  
   150  	for _, tc := range testCases {
   151  		f, err := writePolicy(t, tc.policy)
   152  		require.NoError(t, err)
   153  		defer os.Remove(f)
   154  
   155  		_, err = LoadPolicyFromFile(f)
   156  		assert.Errorf(t, err, "loaded illegal policy with 0 rules from testCase %s", tc.caseName)
   157  	}
   158  }
   159  
   160  func writePolicy(t *testing.T, policy string) (string, error) {
   161  	f, err := ioutil.TempFile("", "policy.yaml")
   162  	require.NoError(t, err)
   163  
   164  	_, err = f.WriteString(policy)
   165  	require.NoError(t, err)
   166  	require.NoError(t, f.Close())
   167  
   168  	return f.Name(), nil
   169  }