mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
refactor: introduce userinfo package in the cli (#8272)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
cdd8b4383f
commit
e8bc38f25b
11 changed files with 114 additions and 59 deletions
cmd/cli/kubectl-kyverno
commands
testdata/user-infos
userinfo
utils/common
test/cli/test/limit-configmap-for-sa
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/output/color"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test/api"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/userinfo"
|
||||
cobrautils "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/cobra"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
reportutils "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/report"
|
||||
|
@ -138,9 +139,9 @@ func (c *ApplyCommandConfig) applyCommandHelper() (*common.ResultCounts, []*unst
|
|||
if err != nil {
|
||||
return rc, uu, skipInvalidPolicies, er, err
|
||||
}
|
||||
var userInfo v1beta1.RequestInfo
|
||||
var userInfo *v1beta1.RequestInfo
|
||||
if c.UserInfoPath != "" {
|
||||
userInfo, err = common.GetUserInfoFromPath(nil, c.UserInfoPath, "")
|
||||
userInfo, err = userinfo.Load(nil, c.UserInfoPath, "")
|
||||
if err != nil {
|
||||
fmt.Printf("Error: failed to load request info\nCause: %s\n", err)
|
||||
osExit(1)
|
||||
|
@ -211,7 +212,7 @@ func (c *ApplyCommandConfig) applyValidatingAdmissionPolicytoResource(validating
|
|||
return rc, resources, skipInvalidPolicies, responses, nil
|
||||
}
|
||||
|
||||
func (c *ApplyCommandConfig) applyPolicytoResource(variables map[string]string, policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, resources []*unstructured.Unstructured, openApiManager openapi.Manager, skipInvalidPolicies SkippedInvalidPolicies, valuesMap map[string]map[string]api.Resource, dClient dclient.Interface, subresources []api.Subresource, globalValMap map[string]string, userInfo v1beta1.RequestInfo, mutateLogPathIsDir bool, namespaceSelectorMap map[string]map[string]string) (*common.ResultCounts, []*unstructured.Unstructured, SkippedInvalidPolicies, []engineapi.EngineResponse, error) {
|
||||
func (c *ApplyCommandConfig) applyPolicytoResource(variables map[string]string, policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, resources []*unstructured.Unstructured, openApiManager openapi.Manager, skipInvalidPolicies SkippedInvalidPolicies, valuesMap map[string]map[string]api.Resource, dClient dclient.Interface, subresources []api.Subresource, globalValMap map[string]string, userInfo *v1beta1.RequestInfo, mutateLogPathIsDir bool, namespaceSelectorMap map[string]map[string]string) (*common.ResultCounts, []*unstructured.Unstructured, SkippedInvalidPolicies, []engineapi.EngineResponse, error) {
|
||||
if len(variables) != 0 {
|
||||
variables = common.SetInStoreContext(policies, variables)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/output/pluralize"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/resource"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/userinfo"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
pathutils "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/path"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
|
@ -48,10 +49,10 @@ func runTest(openApiManager openapi.Manager, testCase test.TestCase, auditWarn b
|
|||
return nil, err
|
||||
}
|
||||
// user info
|
||||
var userInfo v1beta1.RequestInfo
|
||||
var userInfo *v1beta1.RequestInfo
|
||||
if testCase.Test.UserInfo != "" {
|
||||
fmt.Println(" Loading user infos", "...")
|
||||
userInfo, err = common.GetUserInfoFromPath(testCase.Fs, testCase.Test.UserInfo, testDir)
|
||||
userInfo, err = userinfo.Load(testCase.Fs, testCase.Test.UserInfo, testDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error: failed to load request info (%s)", err)
|
||||
}
|
||||
|
|
1
cmd/cli/kubectl-kyverno/testdata/user-infos/invalid.yaml
vendored
Normal file
1
cmd/cli/kubectl-kyverno/testdata/user-infos/invalid.yaml
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
foo: bar
|
4
cmd/cli/kubectl-kyverno/testdata/user-infos/valid.yaml
vendored
Normal file
4
cmd/cli/kubectl-kyverno/testdata/user-infos/valid.yaml
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
clusterRoles:
|
||||
- cluster-admin
|
||||
userInfo:
|
||||
username: molybdenum@somecorp.com
|
39
cmd/cli/kubectl-kyverno/userinfo/userinfo.go
Normal file
39
cmd/cli/kubectl-kyverno/userinfo/userinfo.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package userinfo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
func Load(fs billy.Filesystem, path string, resourcePath string) (*kyvernov1beta1.RequestInfo, error) {
|
||||
var userInfo kyvernov1beta1.RequestInfo
|
||||
if fs != nil {
|
||||
filep, err := fs.Open(filepath.Join(resourcePath, path))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to open userInfo file: %s. \nerror: %s", path, err)
|
||||
}
|
||||
bytes, err := io.ReadAll(filep)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error: failed to read file %s: %w", filep.Name(), err)
|
||||
}
|
||||
if err := yaml.UnmarshalStrict(bytes, &userInfo); err != nil {
|
||||
return nil, sanitizederror.NewWithError("failed to decode yaml", err)
|
||||
}
|
||||
} else {
|
||||
bytes, err := os.ReadFile(filepath.Clean(filepath.Join(resourcePath, path)))
|
||||
if err != nil {
|
||||
return nil, sanitizederror.NewWithError("unable to read yaml", err)
|
||||
}
|
||||
if err := yaml.UnmarshalStrict(bytes, &userInfo); err != nil {
|
||||
return nil, sanitizederror.NewWithError("failed to decode yaml", err)
|
||||
}
|
||||
}
|
||||
return &userInfo, nil
|
||||
}
|
60
cmd/cli/kubectl-kyverno/userinfo/userinfo_test.go
Normal file
60
cmd/cli/kubectl-kyverno/userinfo/userinfo_test.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package userinfo
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fs billy.Filesystem
|
||||
path string
|
||||
resourcePath string
|
||||
want *kyvernov1beta1.RequestInfo
|
||||
wantErr bool
|
||||
}{{
|
||||
name: "empty",
|
||||
fs: nil,
|
||||
path: "",
|
||||
resourcePath: "",
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "invalid",
|
||||
fs: nil,
|
||||
path: "../testdata/user-infos/invalid.yaml",
|
||||
resourcePath: "",
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "valid",
|
||||
fs: nil,
|
||||
path: "../testdata/user-infos/valid.yaml",
|
||||
resourcePath: "",
|
||||
want: &kyvernov1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"cluster-admin"},
|
||||
AdmissionUserInfo: authenticationv1.UserInfo{
|
||||
Username: "molybdenum@somecorp.com",
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := Load(tt.fs, tt.path, tt.resourcePath)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Load() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Load() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ package common
|
|||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -58,7 +57,7 @@ type ApplyPolicyConfig struct {
|
|||
MutateLogPath string
|
||||
MutateLogPathIsDir bool
|
||||
Variables map[string]interface{}
|
||||
UserInfo kyvernov1beta1.RequestInfo
|
||||
UserInfo *kyvernov1beta1.RequestInfo
|
||||
PolicyReport bool
|
||||
NamespaceSelectorMap map[string]map[string]string
|
||||
Stdin bool
|
||||
|
@ -583,50 +582,6 @@ func handleGeneratePolicy(generateResponse *engineapi.EngineResponse, policyCont
|
|||
return newRuleResponse, nil
|
||||
}
|
||||
|
||||
// GetUserInfoFromPath - get the request info as user info from a given path
|
||||
func GetUserInfoFromPath(fs billy.Filesystem, path string, policyResourcePath string) (kyvernov1beta1.RequestInfo, error) {
|
||||
userInfo := &kyvernov1beta1.RequestInfo{}
|
||||
if fs != nil {
|
||||
filep, err := fs.Open(filepath.Join(policyResourcePath, path))
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to open userInfo file: %s. \nerror: %s", path, err)
|
||||
}
|
||||
bytes, err := io.ReadAll(filep)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: failed to read file %s: %v", filep.Name(), err.Error())
|
||||
}
|
||||
userInfoBytes, err := yaml.ToJSON(bytes)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to convert to JSON: %v", err)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(userInfoBytes, userInfo); err != nil {
|
||||
fmt.Printf("failed to decode yaml: %v", err)
|
||||
}
|
||||
} else {
|
||||
var errors []error
|
||||
pathname := filepath.Clean(filepath.Join(policyResourcePath, path))
|
||||
bytes, err := os.ReadFile(pathname)
|
||||
if err != nil {
|
||||
errors = append(errors, sanitizederror.NewWithError("unable to read yaml", err))
|
||||
}
|
||||
userInfoBytes, err := yaml.ToJSON(bytes)
|
||||
if err != nil {
|
||||
errors = append(errors, sanitizederror.NewWithError("failed to convert json", err))
|
||||
}
|
||||
if err := json.Unmarshal(userInfoBytes, userInfo); err != nil {
|
||||
errors = append(errors, sanitizederror.NewWithError("failed to decode yaml", err))
|
||||
}
|
||||
if len(errors) > 0 && log.V(1).Enabled() {
|
||||
fmt.Printf("ignoring errors: \n")
|
||||
for _, e := range errors {
|
||||
fmt.Printf(" %v \n", e.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
return *userInfo, nil
|
||||
}
|
||||
|
||||
func GetGitBranchOrPolicyPaths(gitBranch, repoURL string, policyPaths []string) (string, string) {
|
||||
var gitPathToYamls string
|
||||
if gitBranch == "" {
|
||||
|
|
|
@ -3,7 +3,6 @@ package common
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/resource"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test/api"
|
||||
yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml"
|
||||
|
@ -105,7 +104,7 @@ func Test_NamespaceSelector(t *testing.T) {
|
|||
Policy: policyArray[0],
|
||||
Resource: resourceArray[0],
|
||||
MutateLogPath: "",
|
||||
UserInfo: v1beta1.RequestInfo{},
|
||||
UserInfo: nil,
|
||||
NamespaceSelectorMap: tc.namespaceSelectorMap,
|
||||
Rc: rc,
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ OuterLoop:
|
|||
jp,
|
||||
*updatedResource,
|
||||
operation,
|
||||
&c.UserInfo,
|
||||
c.UserInfo,
|
||||
cfg,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
@ -17,5 +17,4 @@ results:
|
|||
- any-configmap-name-bad
|
||||
result: skip
|
||||
rule: limit-configmap-for-sa-developer
|
||||
userinfo: user_info.yaml
|
||||
variables: variables.yaml
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
subject:
|
||||
kind: ServiceAccount
|
||||
name: another-developer
|
||||
namespace: another-namespace
|
Loading…
Add table
Reference in a new issue