github.com/lukasheimann/cloudfoundrycli@v7.1.0+incompatible/actor/v7action/security_group.go (about) 1 package v7action 2 3 import ( 4 "encoding/json" 5 "io/ioutil" 6 "os" 7 8 "code.cloudfoundry.org/cli/actor/actionerror" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 11 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 12 "code.cloudfoundry.org/cli/resources" 13 ) 14 15 type SecurityGroupSummary struct { 16 Name string 17 Rules []resources.Rule 18 SecurityGroupSpaces []SecurityGroupSpace 19 } 20 21 type SecurityGroupSpace struct { 22 SpaceName string 23 OrgName string 24 Lifecycle string 25 } 26 27 func (actor Actor) BindSecurityGroupToSpaces(securityGroupGUID string, spaces []resources.Space, lifecycle constant.SecurityGroupLifecycle) (Warnings, error) { 28 var ( 29 warnings ccv3.Warnings 30 err error 31 spaceGUIDs []string 32 ) 33 34 for _, space := range spaces { 35 spaceGUIDs = append(spaceGUIDs, space.GUID) 36 } 37 38 switch lifecycle { 39 case constant.SecurityGroupLifecycleRunning: 40 warnings, err = actor.CloudControllerClient.UpdateSecurityGroupRunningSpace(securityGroupGUID, spaceGUIDs) 41 case constant.SecurityGroupLifecycleStaging: 42 warnings, err = actor.CloudControllerClient.UpdateSecurityGroupStagingSpace(securityGroupGUID, spaceGUIDs) 43 default: 44 err = actionerror.InvalidLifecycleError{Lifecycle: string(lifecycle)} 45 } 46 47 return Warnings(warnings), err 48 } 49 50 func (actor Actor) CreateSecurityGroup(name, filePath string) (Warnings, error) { 51 allWarnings := Warnings{} 52 bytes, err := parsePath(filePath) 53 if err != nil { 54 return allWarnings, err 55 } 56 57 var rules []resources.Rule 58 err = json.Unmarshal(bytes, &rules) 59 if err != nil { 60 return allWarnings, err 61 } 62 63 securityGroup := resources.SecurityGroup{Name: name, Rules: rules} 64 65 _, warnings, err := actor.CloudControllerClient.CreateSecurityGroup(securityGroup) 66 allWarnings = append(allWarnings, warnings...) 67 if err != nil { 68 return allWarnings, err 69 } 70 return allWarnings, nil 71 } 72 73 func (actor Actor) GetSecurityGroup(securityGroupName string) (resources.SecurityGroup, Warnings, error) { 74 allWarnings := Warnings{} 75 76 securityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups(ccv3.Query{Key: ccv3.NameFilter, Values: []string{securityGroupName}}) 77 allWarnings = append(allWarnings, warnings...) 78 79 if err != nil { 80 return resources.SecurityGroup{}, allWarnings, err 81 } 82 83 if len(securityGroups) == 0 { 84 return resources.SecurityGroup{}, allWarnings, actionerror.SecurityGroupNotFoundError{Name: securityGroupName} 85 } 86 87 return securityGroups[0], allWarnings, err 88 } 89 90 func (actor Actor) GetSecurityGroupSummary(securityGroupName string) (SecurityGroupSummary, Warnings, error) { 91 allWarnings := Warnings{} 92 securityGroupSummary := SecurityGroupSummary{} 93 securityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups(ccv3.Query{Key: ccv3.NameFilter, Values: []string{securityGroupName}}) 94 95 allWarnings = append(allWarnings, warnings...) 96 97 if err != nil { 98 return securityGroupSummary, allWarnings, err 99 } 100 if len(securityGroups) == 0 { 101 return securityGroupSummary, allWarnings, actionerror.SecurityGroupNotFoundError{Name: securityGroupName} 102 } 103 104 securityGroupSummary.Name = securityGroupName 105 securityGroupSummary.Rules = securityGroups[0].Rules 106 107 var noSecurityGroupSpaces = len(securityGroups[0].StagingSpaceGUIDs) == 0 && len(securityGroups[0].RunningSpaceGUIDs) == 0 108 if noSecurityGroupSpaces { 109 securityGroupSummary.SecurityGroupSpaces = []SecurityGroupSpace{} 110 } else { 111 secGroupSpaces, warnings, err := getSecurityGroupSpaces(actor, securityGroups[0].StagingSpaceGUIDs, securityGroups[0].RunningSpaceGUIDs) 112 allWarnings = append(allWarnings, warnings...) 113 if err != nil { 114 return securityGroupSummary, allWarnings, err 115 } 116 securityGroupSummary.SecurityGroupSpaces = secGroupSpaces 117 } 118 119 return securityGroupSummary, allWarnings, nil 120 } 121 122 func (actor Actor) GetSecurityGroups() ([]SecurityGroupSummary, Warnings, error) { 123 allWarnings := Warnings{} 124 securityGroupSummaries := []SecurityGroupSummary{} 125 securityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups() 126 127 allWarnings = append(allWarnings, warnings...) 128 129 if err != nil { 130 return securityGroupSummaries, allWarnings, err 131 } 132 133 for _, securityGroup := range securityGroups { 134 var securityGroupSummary SecurityGroupSummary 135 securityGroupSummary.Name = securityGroup.Name 136 securityGroupSummary.Rules = securityGroup.Rules 137 138 var securityGroupSpaces []SecurityGroupSpace 139 var noSecurityGroupSpaces = !*securityGroup.StagingGloballyEnabled && !*securityGroup.RunningGloballyEnabled && len(securityGroup.StagingSpaceGUIDs) == 0 && len(securityGroup.RunningSpaceGUIDs) == 0 140 if noSecurityGroupSpaces { 141 securityGroupSpaces = []SecurityGroupSpace{} 142 } 143 144 if *securityGroup.StagingGloballyEnabled { 145 securityGroupSpaces = append(securityGroupSpaces, SecurityGroupSpace{ 146 SpaceName: "<all>", 147 OrgName: "<all>", 148 Lifecycle: "staging", 149 }) 150 } 151 152 if *securityGroup.RunningGloballyEnabled { 153 securityGroupSpaces = append(securityGroupSpaces, SecurityGroupSpace{ 154 SpaceName: "<all>", 155 OrgName: "<all>", 156 Lifecycle: "running", 157 }) 158 } 159 160 secGroupSpaces, warnings, err := getSecurityGroupSpaces(actor, securityGroup.StagingSpaceGUIDs, securityGroup.RunningSpaceGUIDs) 161 allWarnings = append(allWarnings, warnings...) 162 if err != nil { 163 return securityGroupSummaries, allWarnings, err 164 } 165 securityGroupSpaces = append(securityGroupSpaces, secGroupSpaces...) 166 securityGroupSummary.SecurityGroupSpaces = securityGroupSpaces 167 168 securityGroupSummaries = append(securityGroupSummaries, securityGroupSummary) 169 } 170 171 return securityGroupSummaries, allWarnings, nil 172 } 173 174 func (actor Actor) UnbindSecurityGroup(securityGroupName string, orgName string, spaceName string, lifecycle constant.SecurityGroupLifecycle) (Warnings, error) { 175 var allWarnings Warnings 176 177 org, warnings, err := actor.GetOrganizationByName(orgName) 178 allWarnings = append(allWarnings, warnings...) 179 if err != nil { 180 return allWarnings, err 181 } 182 183 space, warnings, err := actor.GetSpaceByNameAndOrganization(spaceName, org.GUID) 184 allWarnings = append(allWarnings, warnings...) 185 if err != nil { 186 return allWarnings, err 187 } 188 189 securityGroup, warnings, err := actor.GetSecurityGroup(securityGroupName) 190 allWarnings = append(allWarnings, warnings...) 191 if err != nil { 192 return allWarnings, err 193 } 194 195 var ccv3Warnings ccv3.Warnings 196 switch lifecycle { 197 case constant.SecurityGroupLifecycleRunning: 198 ccv3Warnings, err = actor.CloudControllerClient.UnbindSecurityGroupRunningSpace(securityGroup.GUID, space.GUID) 199 case constant.SecurityGroupLifecycleStaging: 200 ccv3Warnings, err = actor.CloudControllerClient.UnbindSecurityGroupStagingSpace(securityGroup.GUID, space.GUID) 201 default: 202 return allWarnings, actionerror.InvalidLifecycleError{Lifecycle: string(lifecycle)} 203 } 204 205 allWarnings = append(allWarnings, ccv3Warnings...) 206 207 if err != nil { 208 if _, isNotBoundError := err.(ccerror.SecurityGroupNotBound); isNotBoundError { 209 return allWarnings, actionerror.SecurityGroupNotBoundToSpaceError{ 210 Name: securityGroupName, 211 Space: spaceName, 212 Lifecycle: lifecycle, 213 } 214 } 215 } 216 217 return allWarnings, err 218 } 219 220 func (actor Actor) GetGlobalStagingSecurityGroups() ([]resources.SecurityGroup, Warnings, error) { 221 stagingSecurityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups(ccv3.Query{Key: ccv3.GloballyEnabledStaging, Values: []string{"true"}}) 222 223 return stagingSecurityGroups, Warnings(warnings), err 224 } 225 226 func (actor Actor) GetGlobalRunningSecurityGroups() ([]resources.SecurityGroup, Warnings, error) { 227 runningSecurityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups(ccv3.Query{Key: ccv3.GloballyEnabledRunning, Values: []string{"true"}}) 228 229 return runningSecurityGroups, Warnings(warnings), err 230 } 231 232 func (actor Actor) UpdateSecurityGroup(name, filePath string) (Warnings, error) { 233 allWarnings := Warnings{} 234 235 // parse input file 236 bytes, err := parsePath(filePath) 237 if err != nil { 238 return allWarnings, err 239 } 240 241 var rules []resources.Rule 242 err = json.Unmarshal(bytes, &rules) 243 if err != nil { 244 return allWarnings, err 245 } 246 247 // fetch security group from API 248 securityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups(ccv3.Query{Key: ccv3.NameFilter, Values: []string{name}}) 249 allWarnings = append(allWarnings, warnings...) 250 if err != nil { 251 return allWarnings, err 252 } 253 254 if len(securityGroups) == 0 { 255 return allWarnings, actionerror.SecurityGroupNotFoundError{Name: name} 256 } 257 258 securityGroup := resources.SecurityGroup{ 259 Name: name, 260 GUID: securityGroups[0].GUID, 261 Rules: rules, 262 } 263 264 // update security group 265 _, warnings, err = actor.CloudControllerClient.UpdateSecurityGroup(securityGroup) 266 allWarnings = append(allWarnings, warnings...) 267 if err != nil { 268 return allWarnings, err 269 } 270 271 return allWarnings, nil 272 } 273 274 func (actor Actor) UpdateSecurityGroupGloballyEnabled(securityGroupName string, lifecycle constant.SecurityGroupLifecycle, enabled bool) (Warnings, error) { 275 var allWarnings Warnings 276 277 securityGroup, warnings, err := actor.GetSecurityGroup(securityGroupName) 278 allWarnings = append(allWarnings, warnings...) 279 if err != nil { 280 return allWarnings, err 281 } 282 283 requestBody := resources.SecurityGroup{GUID: securityGroup.GUID} 284 switch lifecycle { 285 case constant.SecurityGroupLifecycleRunning: 286 requestBody.RunningGloballyEnabled = &enabled 287 case constant.SecurityGroupLifecycleStaging: 288 requestBody.StagingGloballyEnabled = &enabled 289 default: 290 return allWarnings, actionerror.InvalidLifecycleError{Lifecycle: string(lifecycle)} 291 } 292 293 _, ccv3Warnings, err := actor.CloudControllerClient.UpdateSecurityGroup(requestBody) 294 allWarnings = append(allWarnings, ccv3Warnings...) 295 296 return allWarnings, err 297 } 298 299 func (actor Actor) DeleteSecurityGroup(securityGroupName string) (Warnings, error) { 300 var allWarnings Warnings 301 302 securityGroup, warnings, err := actor.GetSecurityGroup(securityGroupName) 303 allWarnings = append(allWarnings, warnings...) 304 if err != nil { 305 return allWarnings, err 306 } 307 308 jobURL, ccv3Warnings, err := actor.CloudControllerClient.DeleteSecurityGroup(securityGroup.GUID) 309 allWarnings = append(allWarnings, ccv3Warnings...) 310 if err != nil { 311 return allWarnings, err 312 } 313 314 pollingWarnings, err := actor.CloudControllerClient.PollJob(jobURL) 315 allWarnings = append(allWarnings, pollingWarnings...) 316 return allWarnings, err 317 } 318 319 func getSecurityGroupSpaces(actor Actor, stagingSpaceGUIDs []string, runningSpaceGUIDs []string) ([]SecurityGroupSpace, ccv3.Warnings, error) { 320 var warnings ccv3.Warnings 321 associatedSpaceGuids := runningSpaceGUIDs 322 associatedSpaceGuids = append(associatedSpaceGuids, stagingSpaceGUIDs...) 323 324 var securityGroupSpaces []SecurityGroupSpace 325 if len(associatedSpaceGuids) > 0 { 326 spaces, includes, newWarnings, err := actor.CloudControllerClient.GetSpaces(ccv3.Query{ 327 Key: ccv3.GUIDFilter, 328 Values: associatedSpaceGuids, 329 }, ccv3.Query{ 330 Key: ccv3.Include, 331 Values: []string{"organization"}, 332 }) 333 334 warnings = newWarnings 335 if err != nil { 336 return securityGroupSpaces, warnings, err 337 } 338 339 orgsByGuid := make(map[string]resources.Organization) 340 for _, org := range includes.Organizations { 341 orgsByGuid[org.GUID] = org 342 } 343 344 spacesByGuid := make(map[string]resources.Space) 345 for _, space := range spaces { 346 spacesByGuid[space.GUID] = space 347 } 348 349 for _, runningSpaceGUID := range runningSpaceGUIDs { 350 space := spacesByGuid[runningSpaceGUID] 351 orgGuid := space.Relationships[constant.RelationshipTypeOrganization].GUID 352 securityGroupSpaces = append(securityGroupSpaces, SecurityGroupSpace{ 353 SpaceName: space.Name, 354 OrgName: orgsByGuid[orgGuid].Name, 355 Lifecycle: "running", 356 }) 357 } 358 359 for _, stagingSpaceGUID := range stagingSpaceGUIDs { 360 space := spacesByGuid[stagingSpaceGUID] 361 orgGuid := space.Relationships[constant.RelationshipTypeOrganization].GUID 362 securityGroupSpaces = append(securityGroupSpaces, SecurityGroupSpace{ 363 SpaceName: space.Name, 364 OrgName: orgsByGuid[orgGuid].Name, 365 Lifecycle: "staging", 366 }) 367 } 368 } 369 return securityGroupSpaces, warnings, nil 370 } 371 372 func parsePath(path string) ([]byte, error) { 373 file, err := os.Open(path) 374 if err != nil { 375 return nil, err 376 } 377 378 bytes, err := ioutil.ReadAll(file) 379 if err != nil { 380 return nil, err 381 } 382 383 return bytes, nil 384 }