github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/rules/cloud/policies/google/iam/no_privileged_service_accounts.go (about)

     1  package iam
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/khulnasoft-lab/defsec/pkg/severity"
     7  
     8  	"github.com/khulnasoft-lab/defsec/pkg/state"
     9  
    10  	"github.com/khulnasoft-lab/defsec/pkg/scan"
    11  
    12  	"github.com/khulnasoft-lab/defsec/internal/rules"
    13  
    14  	"github.com/khulnasoft-lab/defsec/pkg/providers"
    15  )
    16  
    17  var CheckNoPrivilegedServiceAccounts = rules.Register(
    18  	scan.Rule{
    19  		AVDID:       "AVD-GCP-0007",
    20  		Provider:    providers.GoogleProvider,
    21  		Service:     "iam",
    22  		ShortCode:   "no-privileged-service-accounts",
    23  		Summary:     "Service accounts should not have roles assigned with excessive privileges",
    24  		Impact:      "Cloud account takeover if a resource using a service account is compromised",
    25  		Resolution:  "Limit service account access to minimal required set",
    26  		Explanation: `Service accounts should have a minimal set of permissions assigned in order to do their job. They should never have excessive access as if compromised, an attacker can escalate privileges and take over the entire account.`,
    27  		Links: []string{
    28  			"https://cloud.google.com/iam/docs/understanding-roles",
    29  		},
    30  		Terraform: &scan.EngineMetadata{
    31  			GoodExamples:        terraformNoPrivilegedServiceAccountsGoodExamples,
    32  			BadExamples:         terraformNoPrivilegedServiceAccountsBadExamples,
    33  			Links:               terraformNoPrivilegedServiceAccountsLinks,
    34  			RemediationMarkdown: terraformNoPrivilegedServiceAccountsRemediationMarkdown,
    35  		},
    36  		Severity: severity.High,
    37  	},
    38  	func(s *state.State) (results scan.Results) {
    39  		for _, project := range s.Google.IAM.AllProjects() {
    40  			for _, member := range project.Members {
    41  				if member.Metadata.IsUnmanaged() {
    42  					continue
    43  				}
    44  				if member.Member.StartsWith("serviceAccount:") {
    45  					if isRolePrivileged(member.Role.Value()) {
    46  						results.Add(
    47  							"Service account is granted a privileged role.",
    48  							member.Role,
    49  						)
    50  					} else {
    51  						results.AddPassed(&member)
    52  					}
    53  
    54  				}
    55  			}
    56  			for _, binding := range project.Bindings {
    57  				if binding.Metadata.IsUnmanaged() {
    58  					continue
    59  				}
    60  				if isRolePrivileged(binding.Role.Value()) {
    61  					for _, member := range binding.Members {
    62  						if member.StartsWith("serviceAccount:") {
    63  							results.Add(
    64  								"Service account is granted a privileged role.",
    65  								binding.Role,
    66  							)
    67  						} else {
    68  							results.AddPassed(&binding)
    69  						}
    70  
    71  					}
    72  				}
    73  			}
    74  		}
    75  		for _, folder := range s.Google.IAM.AllFolders() {
    76  			for _, member := range folder.Members {
    77  				if member.Metadata.IsUnmanaged() {
    78  					continue
    79  				}
    80  				if member.Member.StartsWith("serviceAccount:") {
    81  					if isRolePrivileged(member.Role.Value()) {
    82  						results.Add(
    83  							"Service account is granted a privileged role.",
    84  							member.Role,
    85  						)
    86  					} else {
    87  						results.AddPassed(&member)
    88  					}
    89  
    90  				}
    91  			}
    92  			for _, binding := range folder.Bindings {
    93  				if binding.Metadata.IsUnmanaged() {
    94  					continue
    95  				}
    96  				if isRolePrivileged(binding.Role.Value()) {
    97  					for _, member := range binding.Members {
    98  						if member.StartsWith("serviceAccount:") {
    99  							results.Add(
   100  								"Service account is granted a privileged role.",
   101  								binding.Role,
   102  							)
   103  						} else {
   104  							results.AddPassed(member)
   105  						}
   106  
   107  					}
   108  				}
   109  			}
   110  
   111  		}
   112  
   113  		for _, org := range s.Google.IAM.Organizations {
   114  			for _, member := range org.Members {
   115  				if member.Metadata.IsUnmanaged() {
   116  					continue
   117  				}
   118  				if member.Member.StartsWith("serviceAccount:") {
   119  					if isRolePrivileged(member.Role.Value()) {
   120  						results.Add(
   121  							"Service account is granted a privileged role.",
   122  							member.Role,
   123  						)
   124  					} else {
   125  						results.AddPassed(&member)
   126  					}
   127  
   128  				}
   129  			}
   130  			for _, binding := range org.Bindings {
   131  				if binding.Metadata.IsUnmanaged() {
   132  					continue
   133  				}
   134  				if isRolePrivileged(binding.Role.Value()) {
   135  					for _, member := range binding.Members {
   136  						if member.StartsWith("serviceAccount:") {
   137  							results.Add(
   138  								"Service account is granted a privileged role.",
   139  								binding.Role,
   140  							)
   141  						} else {
   142  							results.AddPassed(member)
   143  						}
   144  
   145  					}
   146  				}
   147  			}
   148  
   149  		}
   150  
   151  		return
   152  	},
   153  )
   154  
   155  func isRolePrivileged(role string) bool {
   156  	switch {
   157  	case role == "roles/owner":
   158  		return true
   159  	case role == "roles/editor":
   160  		return true
   161  	case strings.HasSuffix(strings.ToLower(role), "admin"):
   162  		return true
   163  	}
   164  	return false
   165  }