github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/internal/adapters/terraform/google/iam/project_iam.go (about) 1 package iam 2 3 import ( 4 "strings" 5 6 defsecTypes "github.com/khulnasoft-lab/defsec/pkg/types" 7 8 "github.com/khulnasoft-lab/defsec/pkg/terraform" 9 10 "github.com/khulnasoft-lab/defsec/pkg/providers/google/iam" 11 ) 12 13 // see https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam 14 15 func (a *adapter) adaptProjectIAM() { 16 a.adaptProjectMembers() 17 a.adaptProjectBindings() 18 } 19 20 func (a *adapter) adaptMember(iamBlock *terraform.Block) iam.Member { 21 return AdaptMember(iamBlock, a.modules) 22 } 23 24 func AdaptMember(iamBlock *terraform.Block, modules terraform.Modules) iam.Member { 25 member := iam.Member{ 26 Metadata: iamBlock.GetMetadata(), 27 Member: iamBlock.GetAttribute("member").AsStringValueOrDefault("", iamBlock), 28 Role: iamBlock.GetAttribute("role").AsStringValueOrDefault("", iamBlock), 29 DefaultServiceAccount: defsecTypes.BoolDefault(false, iamBlock.GetMetadata()), 30 } 31 32 memberAttr := iamBlock.GetAttribute("member") 33 if referencedBlock, err := modules.GetReferencedBlock(memberAttr, iamBlock); err == nil { 34 if strings.HasSuffix(referencedBlock.TypeLabel(), "_default_service_account") { 35 member.DefaultServiceAccount = defsecTypes.Bool(true, memberAttr.GetMetadata()) 36 } 37 } 38 39 return member 40 } 41 42 var projectMemberResources = []string{ 43 "google_project_iam_member", 44 "google_cloud_run_service_iam_member", 45 "google_compute_instance_iam_member", 46 "google_compute_subnetwork_iam_member", 47 "google_data_catalog_entry_group_iam_member", 48 "google_folder_iam_member", 49 "google_pubsub_subscription_iam_member", 50 "google_pubsub_topic_iam_member", 51 "google_sourcerepo_repository_iam_member", 52 "google_spanner_database_iam_member", 53 "google_spanner_instance_iam_member", 54 "google_storage_bucket_iam_member", 55 } 56 57 func (a *adapter) adaptProjectMembers() { 58 59 for _, memberType := range projectMemberResources { 60 for _, iamBlock := range a.modules.GetResourcesByType(memberType) { 61 member := a.adaptMember(iamBlock) 62 projectAttr := iamBlock.GetAttribute("project") 63 if projectAttr.IsString() { 64 var foundProject bool 65 projectID := projectAttr.Value().AsString() 66 for i, project := range a.projects { 67 if project.id == projectID { 68 project.project.Members = append(project.project.Members, member) 69 a.projects[i] = project 70 foundProject = true 71 break 72 } 73 } 74 if foundProject { 75 continue 76 } 77 } 78 79 if refBlock, err := a.modules.GetReferencedBlock(projectAttr, iamBlock); err == nil { 80 if refBlock.TypeLabel() == "google_project" { 81 var foundProject bool 82 for i, project := range a.projects { 83 if project.blockID == refBlock.ID() { 84 project.project.Members = append(project.project.Members, member) 85 a.projects[i] = project 86 foundProject = true 87 break 88 } 89 } 90 if foundProject { 91 continue 92 } 93 94 } 95 } 96 97 // we didn't find the project - add an unmanaged one 98 // unless it already belongs to an existing folder 99 var foundFolder bool 100 if refBlock, err := a.modules.GetReferencedBlock(iamBlock.GetAttribute("folder"), iamBlock); err == nil { 101 for _, folder := range a.folders { 102 if folder.blockID == refBlock.ID() { 103 foundFolder = true 104 } 105 } 106 } 107 if foundFolder { 108 continue 109 } 110 111 a.projects = append(a.projects, parentedProject{ 112 project: iam.Project{ 113 Metadata: defsecTypes.NewUnmanagedMetadata(), 114 AutoCreateNetwork: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 115 Members: []iam.Member{member}, 116 Bindings: nil, 117 }, 118 }) 119 } 120 } 121 } 122 123 func (a *adapter) adaptBinding(iamBlock *terraform.Block) iam.Binding { 124 return AdaptBinding(iamBlock, a.modules) 125 } 126 127 func AdaptBinding(iamBlock *terraform.Block, modules terraform.Modules) iam.Binding { 128 binding := iam.Binding{ 129 Metadata: iamBlock.GetMetadata(), 130 Members: nil, 131 Role: iamBlock.GetAttribute("role").AsStringValueOrDefault("", iamBlock), 132 IncludesDefaultServiceAccount: defsecTypes.BoolDefault(false, iamBlock.GetMetadata()), 133 } 134 membersAttr := iamBlock.GetAttribute("members") 135 members := membersAttr.AsStringValues().AsStrings() 136 for _, member := range members { 137 binding.Members = append(binding.Members, defsecTypes.String(member, membersAttr.GetMetadata())) 138 } 139 if referencedBlock, err := modules.GetReferencedBlock(membersAttr, iamBlock); err == nil { 140 if strings.HasSuffix(referencedBlock.TypeLabel(), "_default_service_account") { 141 binding.IncludesDefaultServiceAccount = defsecTypes.Bool(true, membersAttr.GetMetadata()) 142 } 143 } 144 return binding 145 } 146 147 var projectBindingResources = []string{ 148 "google_project_iam_binding", 149 "google_cloud_run_service_iam_binding", 150 "google_compute_instance_iam_binding", 151 "google_compute_subnetwork_iam_binding", 152 "google_data_catalog_entry_group_iam_binding", 153 "google_folder_iam_binding", 154 "google_pubsub_subscription_iam_binding", 155 "google_pubsub_topic_iam_binding", 156 "google_sourcerepo_repository_iam_binding", 157 "google_spanner_database_iam_binding", 158 "google_spanner_instance_iam_binding", 159 "google_storage_bucket_iam_binding", 160 } 161 162 func (a *adapter) adaptProjectDataBindings() { 163 for _, iamBlock := range a.modules.GetResourcesByType("google_project_iam_policy") { 164 165 policyAttr := iamBlock.GetAttribute("policy_data") 166 if policyAttr.IsNil() { 167 continue 168 } 169 policyBlock, err := a.modules.GetReferencedBlock(policyAttr, iamBlock) 170 if err != nil { 171 continue 172 } 173 bindings := ParsePolicyBlock(policyBlock) 174 projectAttr := iamBlock.GetAttribute("project") 175 if projectAttr.IsString() { 176 var foundProject bool 177 projectID := projectAttr.Value().AsString() 178 for i, project := range a.projects { 179 if project.id == projectID { 180 project.project.Bindings = append(project.project.Bindings, bindings...) 181 a.projects[i] = project 182 foundProject = true 183 break 184 } 185 } 186 if foundProject { 187 continue 188 } 189 } 190 191 if refBlock, err := a.modules.GetReferencedBlock(projectAttr, iamBlock); err == nil { 192 if refBlock.TypeLabel() == "google_project" { 193 var foundProject bool 194 for i, project := range a.projects { 195 if project.blockID == refBlock.ID() { 196 project.project.Bindings = append(project.project.Bindings, bindings...) 197 a.projects[i] = project 198 foundProject = true 199 break 200 } 201 } 202 if foundProject { 203 continue 204 } 205 206 } 207 } 208 209 // we didn't find the project - add an unmanaged one 210 a.projects = append(a.projects, parentedProject{ 211 project: iam.Project{ 212 Metadata: defsecTypes.NewUnmanagedMetadata(), 213 AutoCreateNetwork: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 214 Members: nil, 215 Bindings: bindings, 216 }, 217 }) 218 } 219 220 } 221 222 func (a *adapter) adaptProjectBindings() { 223 224 a.adaptProjectDataBindings() 225 226 for _, bindingType := range projectBindingResources { 227 for _, iamBlock := range a.modules.GetResourcesByType(bindingType) { 228 binding := a.adaptBinding(iamBlock) 229 projectAttr := iamBlock.GetAttribute("project") 230 if projectAttr.IsString() { 231 var foundProject bool 232 projectID := projectAttr.Value().AsString() 233 for i, project := range a.projects { 234 if project.id == projectID { 235 project.project.Bindings = append(project.project.Bindings, binding) 236 a.projects[i] = project 237 foundProject = true 238 break 239 } 240 } 241 if foundProject { 242 continue 243 } 244 } 245 246 if refBlock, err := a.modules.GetReferencedBlock(projectAttr, iamBlock); err == nil { 247 if refBlock.TypeLabel() == "google_project" { 248 var foundProject bool 249 for i, project := range a.projects { 250 if project.blockID == refBlock.ID() { 251 project.project.Bindings = append(project.project.Bindings, binding) 252 a.projects[i] = project 253 foundProject = true 254 break 255 } 256 } 257 if foundProject { 258 continue 259 } 260 261 } 262 } 263 264 // we didn't find the project - add an unmanaged one 265 // unless it already belongs to an existing folder 266 var foundFolder bool 267 if refBlock, err := a.modules.GetReferencedBlock(iamBlock.GetAttribute("folder"), iamBlock); err == nil { 268 for _, folder := range a.folders { 269 if folder.blockID == refBlock.ID() { 270 foundFolder = true 271 } 272 } 273 } 274 if foundFolder { 275 continue 276 } 277 a.projects = append(a.projects, parentedProject{ 278 project: iam.Project{ 279 Metadata: defsecTypes.NewUnmanagedMetadata(), 280 AutoCreateNetwork: defsecTypes.BoolDefault(false, defsecTypes.NewUnmanagedMetadata()), 281 Members: nil, 282 Bindings: []iam.Binding{binding}, 283 }, 284 }) 285 } 286 } 287 }