2020-03-06 03:00:18 +05:30
package apply
import (
"fmt"
2020-06-08 17:01:56 +05:30
"os"
2020-07-21 00:41:30 +05:30
"path/filepath"
"strings"
2020-04-03 10:30:52 +05:30
"time"
2021-02-07 20:26:56 -08:00
"github.com/go-git/go-billy/v5/memfs"
2022-04-25 20:20:40 +08:00
"github.com/kyverno/kyverno/api/kyverno/v1beta1"
2022-04-14 17:50:18 +05:30
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
2022-05-17 16:40:51 +02:00
"github.com/kyverno/kyverno/pkg/dclient"
2020-10-15 17:29:07 -07:00
"github.com/kyverno/kyverno/pkg/openapi"
2020-10-07 11:12:31 -07:00
policy2 "github.com/kyverno/kyverno/pkg/policy"
2021-09-02 00:02:55 +05:30
"github.com/kyverno/kyverno/pkg/policyreport"
2020-03-06 03:00:18 +05:30
"github.com/spf13/cobra"
2020-10-15 17:29:07 -07:00
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2020-03-06 03:00:18 +05:30
"k8s.io/cli-runtime/pkg/genericclioptions"
2020-03-20 11:43:21 -07:00
log "sigs.k8s.io/controller-runtime/pkg/log"
2020-11-10 10:49:29 +05:30
yaml1 "sigs.k8s.io/yaml"
2020-03-06 03:00:18 +05:30
)
2020-10-30 16:38:19 +05:30
type Resource struct {
Name string ` json:"name" `
Values map [ string ] string ` json:"values" `
}
type Policy struct {
Name string ` json:"name" `
Resources [ ] Resource ` json:"resources" `
}
type Values struct {
Policies [ ] Policy ` json:"policies" `
}
2021-10-14 22:44:11 +05:30
type SkippedInvalidPolicies struct {
skipped [ ] string
invalid [ ] string
}
2020-12-07 11:26:04 -08:00
var applyHelp = `
2020-11-20 12:27:02 +05:30
To apply on a resource :
kyverno apply / path / to / policy . yaml / path / to / folderOfPolicies -- resource = / path / to / resource1 -- resource = / path / to / resource2
To apply on a cluster :
kyverno apply / path / to / policy . yaml / path / to / folderOfPolicies -- cluster
To apply policy with variables :
1. To apply single policy with variable on single resource use flag "set" .
Example :
kyverno apply / path / to / policy . yaml -- resource / path / to / resource . yaml -- set < variable1 >= < value1 > , < variable2 >= < value2 >
2. To apply multiple policy with variable on multiple resource use flag "values_file" .
Example :
kyverno apply / path / to / policy1 . yaml / path / to / policy2 . yaml -- resource / path / to / resource1 . yaml -- resource / path / to / resource2 . yaml - f / path / to / value . yaml
Format of value . yaml :
policies :
- name : < policy1 name >
2021-08-25 09:17:47 +05:30
rules :
- name : < rule1 name >
values :
< context variable1 in policy1 rule1 > : < value >
< context variable2 in policy1 rule1 > : < value >
- name : < rule2 name >
values :
< context variable1 in policy1 rule2 > : < value >
< context variable2 in policy1 rule2 > : < value >
2020-11-20 12:27:02 +05:30
resources :
- name : < resource1 name >
values :
2021-08-25 09:17:47 +05:30
< variable1 in policy1 > : < value >
< variable2 in policy1 > : < value >
2020-11-20 12:27:02 +05:30
- name : < resource2 name >
values :
2021-08-25 09:17:47 +05:30
< variable1 in policy1 > : < value >
< variable2 in policy1 > : < value >
2020-11-20 12:27:02 +05:30
- name : < policy2 name >
resources :
- name : < resource1 name >
values :
2021-08-25 09:17:47 +05:30
< variable1 in policy2 > : < value >
< variable2 in policy2 > : < value >
2020-11-20 12:27:02 +05:30
- name : < resource2 name >
values :
2021-08-25 09:17:47 +05:30
< variable1 in policy2 > : < value >
< variable2 in policy2 > : < value >
2021-03-10 02:15:45 +05:30
namespaceSelector :
- name : < namespace1 name >
labels :
< label key > : < label value >
- name : < namespace2 name >
labels :
< label key > : < label value >
2020-11-20 12:27:02 +05:30
2020-12-07 11:26:04 -08:00
More info : https : //kyverno.io/docs/kyverno-cli/
`
func Command ( ) * cobra . Command {
var cmd * cobra . Command
var resourcePaths [ ] string
2022-03-16 09:56:47 +05:30
var cluster , policyReport , stdin , registryAccess bool
2022-04-12 09:30:49 +05:30
var mutateLogPath , variablesString , valuesFile , namespace , userInfoPath string
2020-12-07 11:26:04 -08:00
cmd = & cobra . Command {
Use : "apply" ,
Short : "applies policies on resources" ,
Example : applyHelp ,
2020-03-06 03:00:18 +05:30
RunE : func ( cmd * cobra . Command , policyPaths [ ] string ) ( err error ) {
defer func ( ) {
if err != nil {
2020-12-07 11:26:04 -08:00
if ! sanitizederror . IsErrorSanitized ( err ) {
2020-03-20 11:43:21 -07:00
log . Log . Error ( err , "failed to sanitize" )
2020-08-05 23:53:27 +05:30
err = fmt . Errorf ( "internal error" )
2020-03-06 03:00:18 +05:30
}
}
} ( )
2022-04-12 09:30:49 +05:30
rc , resources , skipInvalidPolicies , pvInfos , err := applyCommandHelper ( resourcePaths , userInfoPath , cluster , policyReport , mutateLogPath , variablesString , valuesFile , namespace , policyPaths , stdin , registryAccess )
2020-10-30 16:38:19 +05:30
if err != nil {
return err
2020-08-11 22:59:50 +05:30
}
2022-07-14 02:07:51 +05:30
PrintReportOrViolation ( policyReport , rc , resourcePaths , len ( resources ) , skipInvalidPolicies , stdin , pvInfos )
2020-12-20 01:21:31 +05:30
return nil
} ,
}
cmd . Flags ( ) . StringArrayVarP ( & resourcePaths , "resource" , "r" , [ ] string { } , "Path to resource files" )
cmd . Flags ( ) . BoolVarP ( & cluster , "cluster" , "c" , false , "Checks if policies should be applied to cluster in the current context" )
cmd . Flags ( ) . StringVarP ( & mutateLogPath , "output" , "o" , "" , "Prints the mutated resources in provided file/directory" )
2021-08-02 16:38:43 +05:30
// currently `set` flag supports variable for single policy applied on single resource
2022-04-12 09:30:49 +05:30
cmd . Flags ( ) . StringVarP ( & userInfoPath , "userinfo" , "u" , "" , "Admission Info including Roles, Cluster Roles and Subjects" )
2020-12-20 01:21:31 +05:30
cmd . Flags ( ) . StringVarP ( & variablesString , "set" , "s" , "" , "Variables that are required" )
cmd . Flags ( ) . StringVarP ( & valuesFile , "values-file" , "f" , "" , "File containing values for policy variables" )
2022-07-18 12:42:19 +05:30
cmd . Flags ( ) . BoolVarP ( & policyReport , "policy-report" , "p" , false , "Generates policy report when passed (default policyviolation)" )
2020-12-20 01:21:31 +05:30
cmd . Flags ( ) . StringVarP ( & namespace , "namespace" , "n" , "" , "Optional Policy parameter passed with cluster flag" )
2021-03-26 23:33:45 +05:30
cmd . Flags ( ) . BoolVarP ( & stdin , "stdin" , "i" , false , "Optional mutate policy parameter to pipe directly through to kubectl" )
2022-03-16 09:56:47 +05:30
cmd . Flags ( ) . BoolVarP ( & registryAccess , "registry" , "" , false , "If set to true, access the image registry using local docker credentials to populate external data" )
2020-12-20 01:21:31 +05:30
return cmd
}
2020-08-05 23:53:27 +05:30
2022-04-12 09:30:49 +05:30
func applyCommandHelper ( resourcePaths [ ] string , userInfoPath string , cluster bool , policyReport bool , mutateLogPath string ,
2022-05-17 08:19:03 +02:00
variablesString string , valuesFile string , namespace string , policyPaths [ ] string , stdin bool , registryAccess bool ,
) ( rc * common . ResultCounts , resources [ ] * unstructured . Unstructured , skipInvalidPolicies SkippedInvalidPolicies , pvInfos [ ] policyreport . Info , err error ) {
2021-04-29 22:39:44 +05:30
store . SetMock ( true )
2022-03-16 09:56:47 +05:30
store . SetRegistryAccess ( registryAccess )
2020-12-20 01:21:31 +05:30
kubernetesConfig := genericclioptions . NewConfigFlags ( true )
2021-02-02 18:43:19 +05:30
fs := memfs . New ( )
2020-10-16 19:56:32 +05:30
2020-12-20 01:21:31 +05:30
if valuesFile != "" && variablesString != "" {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "pass the values either using set flag or values_file flag" , err )
2020-12-20 01:21:31 +05:30
}
2020-12-07 11:26:04 -08:00
2021-09-20 22:16:57 +05:30
variables , globalValMap , valuesMap , namespaceSelectorMap , err := common . GetVariable ( variablesString , valuesFile , fs , false , "" )
2020-12-20 01:21:31 +05:30
if err != nil {
if ! sanitizederror . IsErrorSanitized ( err ) {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "failed to decode yaml" , err )
2020-12-20 01:21:31 +05:30
}
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , err
2020-12-20 01:21:31 +05:30
}
2020-10-16 19:56:32 +05:30
2020-12-20 01:21:31 +05:30
openAPIController , err := openapi . NewOpenAPIController ( )
if err != nil {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "failed to initialize openAPIController" , err )
2020-12-20 01:21:31 +05:30
}
2020-07-21 00:41:30 +05:30
2022-05-17 16:40:51 +02:00
var dClient dclient . Interface
2020-12-20 01:21:31 +05:30
if cluster {
restConfig , err := kubernetesConfig . ToRESTConfig ( )
if err != nil {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , err
2020-12-20 01:21:31 +05:30
}
2022-05-17 16:40:51 +02:00
dClient , err = dclient . NewClient ( restConfig , 15 * time . Minute , make ( chan struct { } ) )
2020-12-20 01:21:31 +05:30
if err != nil {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , err
2020-12-20 01:21:31 +05:30
}
}
2020-03-06 03:00:18 +05:30
2020-12-20 01:21:31 +05:30
if len ( policyPaths ) == 0 {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "require policy" , err )
2020-12-20 01:21:31 +05:30
}
2020-11-11 17:10:38 +05:30
2020-12-20 01:21:31 +05:30
if ( len ( policyPaths ) > 0 && policyPaths [ 0 ] == "-" ) && len ( resourcePaths ) > 0 && resourcePaths [ 0 ] == "-" {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "a stdin pipe can be used for either policies or resources, not both" , err )
2020-12-20 01:21:31 +05:30
}
2020-11-11 11:57:23 +05:30
2021-02-18 01:00:41 +05:30
policies , err := common . GetPoliciesFromPaths ( fs , policyPaths , false , "" )
2020-12-20 01:21:31 +05:30
if err != nil {
fmt . Printf ( "Error: failed to load policies\nCause: %s\n" , err )
os . Exit ( 1 )
}
2020-07-10 14:56:07 +05:30
2020-12-20 01:21:31 +05:30
if len ( resourcePaths ) == 0 && ! cluster {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "resource file(s) or cluster required" , err )
2020-12-20 01:21:31 +05:30
}
2020-08-18 21:03:00 -07:00
2020-12-20 01:21:31 +05:30
mutateLogPathIsDir , err := checkMutateLogPath ( mutateLogPath )
if err != nil {
if ! sanitizederror . IsErrorSanitized ( err ) {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "failed to create file/folder" , err )
2020-12-20 01:21:31 +05:30
}
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , err
2020-12-20 01:21:31 +05:30
}
2020-08-18 21:03:00 -07:00
2021-03-12 06:00:37 +05:30
// empty the previous contents of the file just in case if the file already existed before with some content(so as to perform overwrites)
// the truncation of files for the case when mutateLogPath is dir, is handled under pkg/kyverno/apply/common.go
2021-03-17 01:27:31 +05:30
if ! mutateLogPathIsDir && mutateLogPath != "" {
2021-10-13 10:48:45 -07:00
mutateLogPath = filepath . Clean ( mutateLogPath )
2021-10-14 00:05:13 +02:00
// Necessary for us to include the file via variable as it is part of the CLI.
2022-05-17 08:19:03 +02:00
_ , err := os . OpenFile ( mutateLogPath , os . O_TRUNC | os . O_WRONLY , 0 o600 ) // #nosec G304
2021-03-12 06:00:37 +05:30
if err != nil {
if ! sanitizederror . IsErrorSanitized ( err ) {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "failed to truncate the existing file at " + mutateLogPath , err )
2021-03-12 06:00:37 +05:30
}
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , err
2021-03-12 06:00:37 +05:30
}
}
2022-03-18 17:16:42 +01:00
mutatedPolicies , err := common . MutatePolicies ( policies )
2020-12-20 01:21:31 +05:30
if err != nil {
if ! sanitizederror . IsErrorSanitized ( err ) {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "failed to mutate policy" , err )
2020-12-20 01:21:31 +05:30
}
}
2020-11-19 15:03:15 +05:30
2021-09-03 16:41:13 +05:30
err = common . PrintMutatedPolicy ( mutatedPolicies )
if err != nil {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "failed to marsal mutated policy" , err )
2021-09-01 00:07:19 +05:30
}
2021-02-18 01:00:41 +05:30
resources , err = common . GetResourceAccordingToResourcePath ( fs , resourcePaths , cluster , mutatedPolicies , dClient , namespace , policyReport , false , "" )
2020-12-20 01:21:31 +05:30
if err != nil {
fmt . Printf ( "Error: failed to load resources\nCause: %s\n" , err )
os . Exit ( 1 )
}
2020-03-06 03:00:18 +05:30
2021-08-02 16:38:43 +05:30
if ( len ( resources ) > 1 || len ( mutatedPolicies ) > 1 ) && variablesString != "" {
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( "currently `set` flag supports variable for single policy applied on single resource " , nil )
2021-08-02 16:38:43 +05:30
}
2022-04-12 09:30:49 +05:30
// get the user info as request info from a different file
2022-04-25 20:20:40 +08:00
var userInfo v1beta1 . RequestInfo
2022-05-11 20:51:13 +05:30
var subjectInfo store . Subject
2022-04-12 09:30:49 +05:30
if userInfoPath != "" {
2022-05-11 20:51:13 +05:30
userInfo , subjectInfo , err = common . GetUserInfoFromPath ( fs , userInfoPath , false , "" )
2022-04-12 09:30:49 +05:30
if err != nil {
fmt . Printf ( "Error: failed to load request info\nCause: %s\n" , err )
os . Exit ( 1 )
}
2022-05-11 20:51:13 +05:30
store . SetSubjects ( subjectInfo )
2022-04-12 09:30:49 +05:30
}
2021-08-02 16:38:43 +05:30
if variablesString != "" {
2021-09-02 23:11:35 +05:30
variables = common . SetInStoreContext ( mutatedPolicies , variables )
2021-08-02 16:38:43 +05:30
}
2020-12-20 01:21:31 +05:30
msgPolicies := "1 policy"
if len ( mutatedPolicies ) > 1 {
msgPolicies = fmt . Sprintf ( "%d policies" , len ( policies ) )
}
2020-11-19 15:03:15 +05:30
2020-12-20 01:21:31 +05:30
msgResources := "1 resource"
if len ( resources ) > 1 {
msgResources = fmt . Sprintf ( "%d resources" , len ( resources ) )
}
2020-08-22 01:21:29 +05:30
2020-12-20 01:21:31 +05:30
if len ( mutatedPolicies ) > 0 && len ( resources ) > 0 {
2021-03-26 23:33:45 +05:30
if ! stdin {
2021-09-01 18:51:31 +05:30
fmt . Printf ( "\nApplying %s to %s... \n(Total number of result count may vary as the policy is mutated by Kyverno. To check the mutated policy please try with log level 5)\n" , msgPolicies , msgResources )
2021-03-26 23:33:45 +05:30
}
2020-12-20 01:21:31 +05:30
}
2020-08-11 22:59:50 +05:30
2021-08-31 21:18:54 +05:30
rc = & common . ResultCounts { }
2021-10-14 22:44:11 +05:30
skipInvalidPolicies . skipped = make ( [ ] string , 0 )
skipInvalidPolicies . invalid = make ( [ ] string , 0 )
2020-08-11 22:59:50 +05:30
2020-12-20 01:21:31 +05:30
for _ , policy := range mutatedPolicies {
2022-03-16 00:50:33 -04:00
_ , err := policy2 . Validate ( policy , nil , true , openAPIController )
2020-12-20 01:21:31 +05:30
if err != nil {
2022-01-04 17:36:33 -08:00
log . Log . Error ( err , "policy validation error" )
2021-10-14 22:44:11 +05:30
if strings . HasPrefix ( err . Error ( ) , "variable 'element.name'" ) {
2022-03-31 08:44:00 +02:00
skipInvalidPolicies . invalid = append ( skipInvalidPolicies . invalid , policy . GetName ( ) )
2021-10-14 22:44:11 +05:30
} else {
2022-03-31 08:44:00 +02:00
skipInvalidPolicies . skipped = append ( skipInvalidPolicies . skipped , policy . GetName ( ) )
2021-10-14 22:44:11 +05:30
}
2022-01-04 17:36:33 -08:00
2020-12-20 01:21:31 +05:30
continue
}
2020-08-12 13:39:06 +05:30
2021-11-03 11:16:55 -07:00
matches := common . HasVariables ( policy )
2021-07-24 00:02:48 +05:30
variable := common . RemoveDuplicateAndObjectVariables ( matches )
2021-08-31 16:24:31 +05:30
if len ( variable ) > 0 {
if len ( variables ) == 0 {
2021-08-31 17:59:18 +05:30
// check policy in variable file
2022-03-31 08:44:00 +02:00
if valuesFile == "" || valuesMap [ policy . GetName ( ) ] == nil {
skipInvalidPolicies . skipped = append ( skipInvalidPolicies . skipped , policy . GetName ( ) )
2021-08-31 16:24:31 +05:30
continue
}
2020-03-06 03:00:18 +05:30
}
2020-12-20 01:21:31 +05:30
}
2020-03-06 03:00:18 +05:30
2021-09-03 16:41:13 +05:30
kindOnwhichPolicyIsApplied := common . GetKindsFromPolicy ( policy )
2021-09-01 18:51:31 +05:30
2020-12-20 01:21:31 +05:30
for _ , resource := range resources {
2021-09-20 22:16:57 +05:30
thisPolicyResourceValues , err := common . CheckVariableForPolicy ( valuesMap , globalValMap , policy . GetName ( ) , resource . GetName ( ) , resource . GetKind ( ) , variables , kindOnwhichPolicyIsApplied , variable )
2021-09-03 16:41:13 +05:30
if err != nil {
2022-03-31 08:44:00 +02:00
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( fmt . Sprintf ( "policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag" , policy . GetName ( ) , resource . GetName ( ) ) , err )
2020-12-20 01:21:31 +05:30
}
2022-05-25 19:56:22 +05:30
_ , info , err := common . ApplyPolicyOnResource ( policy , resource , mutateLogPath , mutateLogPathIsDir , thisPolicyResourceValues , userInfo , policyReport , namespaceSelectorMap , stdin , rc , true , nil )
2020-12-20 01:21:31 +05:30
if err != nil {
2022-03-31 08:44:00 +02:00
return rc , resources , skipInvalidPolicies , pvInfos , sanitizederror . NewWithError ( fmt . Errorf ( "failed to apply policy %v on resource %v" , policy . GetName ( ) , resource . GetName ( ) ) . Error ( ) , err )
2020-12-20 01:21:31 +05:30
}
2021-09-02 00:02:55 +05:30
pvInfos = append ( pvInfos , info )
2020-12-20 01:21:31 +05:30
}
2020-03-06 03:00:18 +05:30
}
2021-10-14 22:44:11 +05:30
return rc , resources , skipInvalidPolicies , pvInfos , nil
2020-03-06 03:00:18 +05:30
}
2020-10-30 16:38:19 +05:30
// checkMutateLogPath - checking path for printing mutated resource (-o flag)
2020-11-03 01:25:32 +05:30
func checkMutateLogPath ( mutateLogPath string ) ( mutateLogPathIsDir bool , err error ) {
2020-10-30 16:38:19 +05:30
if mutateLogPath != "" {
spath := strings . Split ( mutateLogPath , "/" )
sfileName := strings . Split ( spath [ len ( spath ) - 1 ] , "." )
if sfileName [ len ( sfileName ) - 1 ] == "yml" || sfileName [ len ( sfileName ) - 1 ] == "yaml" {
mutateLogPathIsDir = false
} else {
mutateLogPathIsDir = true
}
err := createFileOrFolder ( mutateLogPath , mutateLogPathIsDir )
if err != nil {
2020-12-07 11:26:04 -08:00
if ! sanitizederror . IsErrorSanitized ( err ) {
return mutateLogPathIsDir , sanitizederror . NewWithError ( "failed to create file/folder." , err )
2020-10-30 16:38:19 +05:30
}
return mutateLogPathIsDir , err
}
}
return mutateLogPathIsDir , err
}
2022-07-14 02:07:51 +05:30
// PrintReportOrViolation - printing policy report/violations
func PrintReportOrViolation ( policyReport bool , rc * common . ResultCounts , resourcePaths [ ] string , resourcesLen int , skipInvalidPolicies SkippedInvalidPolicies , stdin bool , pvInfos [ ] policyreport . Info ) {
2021-10-29 11:16:13 +01:00
divider := "----------------------------------------------------------------------"
2021-10-14 22:44:11 +05:30
if len ( skipInvalidPolicies . skipped ) > 0 {
2021-10-29 11:16:13 +01:00
fmt . Println ( divider )
fmt . Println ( "Policies Skipped (as required variables are not provided by the user):" )
2021-10-14 22:44:11 +05:30
for i , policyName := range skipInvalidPolicies . skipped {
2021-10-29 11:16:13 +01:00
fmt . Printf ( "%d. %s\n" , i + 1 , policyName )
2021-10-14 22:44:11 +05:30
}
2021-10-29 11:16:13 +01:00
fmt . Println ( divider )
2021-10-14 22:44:11 +05:30
}
if len ( skipInvalidPolicies . invalid ) > 0 {
2021-10-29 11:16:13 +01:00
fmt . Println ( divider )
fmt . Println ( "Invalid Policies:" )
2021-10-14 22:44:11 +05:30
for i , policyName := range skipInvalidPolicies . invalid {
2021-10-29 11:16:13 +01:00
fmt . Printf ( "%d. %s\n" , i + 1 , policyName )
2021-08-31 16:24:31 +05:30
}
2021-10-29 11:16:13 +01:00
fmt . Println ( divider )
2021-08-31 16:24:31 +05:30
}
2020-10-30 16:38:19 +05:30
if policyReport {
2021-09-02 01:06:29 +05:30
resps := buildPolicyReports ( pvInfos )
2020-11-19 11:52:31 +05:30
if len ( resps ) > 0 || resourcesLen == 0 {
2021-10-29 11:16:13 +01:00
fmt . Println ( divider )
fmt . Println ( "POLICY REPORT:" )
fmt . Println ( divider )
2021-07-09 18:01:46 -07:00
report , _ := generateCLIRaw ( resps )
2020-11-01 22:32:12 +05:30
yamlReport , _ := yaml1 . Marshal ( report )
fmt . Println ( string ( yamlReport ) )
2020-10-30 16:38:19 +05:30
} else {
2021-10-29 11:16:13 +01:00
fmt . Println ( divider )
fmt . Println ( "POLICY REPORT: skip generating policy report (no validate policy found/resource skipped)" )
2020-10-30 16:38:19 +05:30
}
} else {
2021-03-26 23:33:45 +05:30
if ! stdin {
fmt . Printf ( "\npass: %d, fail: %d, warn: %d, error: %d, skip: %d \n" ,
2021-08-31 21:18:54 +05:30
rc . Pass , rc . Fail , rc . Warn , rc . Error , rc . Skip )
2021-03-26 23:33:45 +05:30
}
2021-09-03 17:17:22 +05:30
}
2020-10-30 16:38:19 +05:30
2021-09-03 17:17:22 +05:30
if rc . Fail > 0 || rc . Error > 0 {
os . Exit ( 1 )
2020-10-30 16:38:19 +05:30
}
}
2020-08-18 21:03:00 -07:00
// createFileOrFolder - creating file or folder according to path provided
2020-08-22 01:21:29 +05:30
func createFileOrFolder ( mutateLogPath string , mutateLogPathIsDir bool ) error {
mutateLogPath = filepath . Clean ( mutateLogPath )
_ , err := os . Stat ( mutateLogPath )
2020-07-21 00:41:30 +05:30
if err != nil {
if os . IsNotExist ( err ) {
2020-08-22 01:21:29 +05:30
if ! mutateLogPathIsDir {
2020-11-17 12:01:01 -08:00
// check the folder existence, then create the file
2020-07-21 10:33:38 +05:30
var folderPath string
2020-08-22 01:21:29 +05:30
s := strings . Split ( mutateLogPath , "/" )
2020-07-21 10:33:38 +05:30
if len ( s ) > 1 {
2020-08-22 01:21:29 +05:30
folderPath = mutateLogPath [ : len ( mutateLogPath ) - len ( s [ len ( s ) - 1 ] ) - 1 ]
2020-07-21 10:33:38 +05:30
_ , err := os . Stat ( folderPath )
if os . IsNotExist ( err ) {
2022-05-17 08:19:03 +02:00
errDir := os . MkdirAll ( folderPath , 0 o750 )
2020-07-21 10:33:38 +05:30
if errDir != nil {
2021-10-14 22:44:11 +05:30
return sanitizederror . NewWithError ( "failed to create directory" , err )
2020-07-21 10:33:38 +05:30
}
2020-07-21 00:41:30 +05:30
}
}
2021-10-13 10:48:45 -07:00
mutateLogPath = filepath . Clean ( mutateLogPath )
2021-10-14 00:05:13 +02:00
// Necessary for us to create the file via variable as it is part of the CLI.
2022-05-17 08:19:03 +02:00
file , err := os . OpenFile ( mutateLogPath , os . O_RDONLY | os . O_CREATE , 0 o600 ) // #nosec G304
2020-07-21 00:41:30 +05:30
if err != nil {
2021-10-14 22:44:11 +05:30
return sanitizederror . NewWithError ( "failed to create file" , err )
2020-07-21 00:41:30 +05:30
}
err = file . Close ( )
if err != nil {
2021-10-14 22:44:11 +05:30
return sanitizederror . NewWithError ( "failed to close file" , err )
2020-07-21 00:41:30 +05:30
}
} else {
2022-05-17 08:19:03 +02:00
errDir := os . MkdirAll ( mutateLogPath , 0 o750 )
2020-07-21 00:41:30 +05:30
if errDir != nil {
2021-10-14 22:44:11 +05:30
return sanitizederror . NewWithError ( "failed to create directory" , err )
2020-07-21 00:41:30 +05:30
}
}
} else {
2021-10-14 22:44:11 +05:30
return sanitizederror . NewWithError ( "failed to describe file" , err )
2020-07-21 00:41:30 +05:30
}
}
return nil
}