github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/nsxt_firewall_group.go (about) 1 /* 2 * Copyright 2021 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. 3 */ 4 5 package govcd 6 7 import ( 8 "errors" 9 "fmt" 10 "net/url" 11 12 "github.com/vmware/go-vcloud-director/v2/types/v56" 13 ) 14 15 // NsxtFirewallGroup uses OpenAPI endpoint to operate NSX-T Security Groups and IP Sets which use 16 // the same Firewall Group API endpoint 17 // 18 // IP sets are groups of objects to which the firewall rules apply. Combining multiple objects into 19 // IP sets helps reduce the total number of firewall rules to be created. 20 // 21 // Security groups are groups of Org Vdc networks to which distributed firewall rules apply. 22 // Grouping networks helps you to reduce the total number of distributed firewall rules to be 23 // created. 24 type NsxtFirewallGroup struct { 25 NsxtFirewallGroup *types.NsxtFirewallGroup 26 client *Client 27 } 28 29 // CreateNsxtFirewallGroup allows users to create NSX-T Firewall Group 30 func (vdc *Vdc) CreateNsxtFirewallGroup(firewallGroupConfig *types.NsxtFirewallGroup) (*NsxtFirewallGroup, error) { 31 return createNsxtFirewallGroup(vdc.client, firewallGroupConfig) 32 } 33 34 // CreateNsxtFirewallGroup allows users to create NSX-T Firewall Group 35 func (egw *NsxtEdgeGateway) CreateNsxtFirewallGroup(firewallGroupConfig *types.NsxtFirewallGroup) (*NsxtFirewallGroup, error) { 36 return createNsxtFirewallGroup(egw.client, firewallGroupConfig) 37 } 38 39 // CreateNsxtFirewallGroup allows users to create NSX-T Firewall Group 40 func (vdcGroup *VdcGroup) CreateNsxtFirewallGroup(firewallGroupConfig *types.NsxtFirewallGroup) (*NsxtFirewallGroup, error) { 41 return createNsxtFirewallGroup(vdcGroup.client, firewallGroupConfig) 42 } 43 44 // GetAllNsxtFirewallGroups allows users to retrieve all Firewall Groups for Org 45 // firewallGroupType can be one of the following: 46 // * types.FirewallGroupTypeSecurityGroup - for NSX-T Security Groups 47 // * types.FirewallGroupTypeIpSet - for NSX-T IP Sets 48 // * "" (empty) - search will not be limited and will get both - IP Sets and Security Groups 49 // 50 // It is possible to add additional filtering by using queryParameters of type 'url.Values'. 51 // One special filter is `_context==` filtering. Value can be one of the following: 52 // 53 // * Org Vdc Network ID (_context==networkId) - Returns all the firewall groups which the specified 54 // network is a member of. 55 // 56 // * Edge Gateway ID (_context==edgeGatewayId) - Returns all the firewall groups which are available 57 // to the specific edge gateway. Or use a shorthand NsxtEdgeGateway.GetAllNsxtFirewallGroups() which 58 // automatically injects this filter. 59 // 60 // * Network Provider ID (_context==networkProviderId) - Returns all the firewall groups which are 61 // available under a specific network provider. This context requires system admin privilege. 62 // 'networkProviderId' is NSX-T manager ID 63 func (org *Org) GetAllNsxtFirewallGroups(queryParameters url.Values, firewallGroupType string) ([]*NsxtFirewallGroup, error) { 64 queryParams := copyOrNewUrlValues(queryParameters) 65 if firewallGroupType != "" { 66 queryParams = queryParameterFilterAnd(fmt.Sprintf("typeValue==%s", firewallGroupType), queryParameters) 67 } 68 69 return getAllNsxtFirewallGroups(org.client, queryParams) 70 } 71 72 // GetAllNsxtFirewallGroups allows users to retrieve all NSX-T Firewall Groups 73 func (vdc *Vdc) GetAllNsxtFirewallGroups(queryParameters url.Values, firewallGroupType string) ([]*NsxtFirewallGroup, error) { 74 if vdc.IsNsxv() { 75 return nil, errors.New("only NSX-T VDCs support Firewall Groups") 76 } 77 return getAllNsxtFirewallGroups(vdc.client, queryParameters) 78 } 79 80 // GetAllNsxtFirewallGroups allows users to retrieve all NSX-T Firewall Groups in a particular Edge Gateway 81 // firewallGroupType can be one of the following: 82 // * types.FirewallGroupTypeSecurityGroup - for NSX-T Security Groups 83 // * types.FirewallGroupTypeIpSet - for NSX-T IP Sets 84 // * "" (empty) - search will not be limited and will get both - IP Sets and Security Groups 85 func (egw *NsxtEdgeGateway) GetAllNsxtFirewallGroups(queryParameters url.Values, firewallGroupType string) ([]*NsxtFirewallGroup, error) { 86 queryParams := copyOrNewUrlValues(queryParameters) 87 88 if firewallGroupType != "" { 89 queryParams = queryParameterFilterAnd(fmt.Sprintf("typeValue==%s", firewallGroupType), queryParameters) 90 } 91 92 // Automatically inject Edge Gateway filter because this is an Edge Gateway scoped query 93 queryParams = queryParameterFilterAnd("_context=="+egw.EdgeGateway.ID, queryParams) 94 95 return getAllNsxtFirewallGroups(egw.client, queryParams) 96 } 97 98 // GetNsxtFirewallGroupByName allows users to retrieve Firewall Group by Name 99 // firewallGroupType can be one of the following: 100 // * types.FirewallGroupTypeSecurityGroup - for NSX-T Security Groups 101 // * types.FirewallGroupTypeIpSet - for NSX-T IP Sets 102 // * "" (empty) - search will not be limited and will get both - IP Sets and Security Groups 103 // 104 // Note. One might get an error if IP Set and Security Group exist with the same name (two objects 105 // of the same type cannot exist) and firewallGroupType is left empty. 106 func (org *Org) GetNsxtFirewallGroupByName(name, firewallGroupType string) (*NsxtFirewallGroup, error) { 107 queryParameters := url.Values{} 108 if firewallGroupType != "" { 109 queryParameters = queryParameterFilterAnd(fmt.Sprintf("typeValue==%s", firewallGroupType), queryParameters) 110 } 111 112 return getNsxtFirewallGroupByName(org.client, name, queryParameters) 113 } 114 115 // GetNsxtFirewallGroupByName allows users to retrieve Firewall Group by Name 116 // firewallGroupType can be one of the following: 117 // * types.FirewallGroupTypeSecurityGroup - for NSX-T Security Groups 118 // * types.FirewallGroupTypeIpSet - for NSX-T IP Sets 119 // * "" (empty) - search will not be limited and will get both - IP Sets and Security Groups 120 // 121 // Note. One might get an error if IP Set and Security Group exist with the same name (two objects 122 // of the same type cannot exist) and firewallGroupType is left empty. 123 func (vdc *Vdc) GetNsxtFirewallGroupByName(name, firewallGroupType string) (*NsxtFirewallGroup, error) { 124 125 queryParameters := url.Values{} 126 if firewallGroupType != "" { 127 queryParameters = queryParameterFilterAnd(fmt.Sprintf("typeValue==%s", firewallGroupType), queryParameters) 128 } 129 return getNsxtFirewallGroupByName(vdc.client, name, queryParameters) 130 } 131 132 // GetNsxtFirewallGroupByName allows users to retrieve Firewall Group by Name in a particular VDC Group 133 // firewallGroupType can be one of the following: 134 // * types.FirewallGroupTypeSecurityGroup - for NSX-T Static Security Groups 135 // * types.FirewallGroupTypeVmCriteria - for NSX-T Dynamic Security Groups 136 // * types.FirewallGroupTypeIpSet - for NSX-T IP Sets 137 // * "" (empty) - search will not be limited and will get both - IP Sets and Security Groups 138 // 139 // Note. One might get an error if IP Set and Security Group exist with the same name (two objects 140 // of the same type cannot exist) and firewallGroupType is left empty. 141 func (vdcGroup *VdcGroup) GetNsxtFirewallGroupByName(name string, firewallGroupType string) (*NsxtFirewallGroup, error) { 142 queryParameters := url.Values{} 143 144 if firewallGroupType != "" { 145 queryParameters = queryParameterFilterAnd(fmt.Sprintf("typeValue==%s", firewallGroupType), queryParameters) 146 } 147 148 // Automatically inject Edge Gateway filter because this is an Edge Gateway scoped query 149 queryParameters = queryParameterFilterAnd("ownerRef.id=="+vdcGroup.VdcGroup.Id, queryParameters) 150 151 return getNsxtFirewallGroupByName(vdcGroup.client, name, queryParameters) 152 } 153 154 // GetNsxtFirewallGroupByName allows users to retrieve Firewall Group by Name in a particular Edge Gateway 155 // firewallGroupType can be one of the following: 156 // * types.FirewallGroupTypeSecurityGroup - for NSX-T Security Groups 157 // * types.FirewallGroupTypeIpSet - for NSX-T IP Sets 158 // * "" (empty) - search will not be limited and will get both - IP Sets and Security Groups 159 // 160 // Note. One might get an error if IP Set and Security Group exist with the same name (two objects 161 // of the same type cannot exist) and firewallGroupType is left empty. 162 func (egw *NsxtEdgeGateway) GetNsxtFirewallGroupByName(name string, firewallGroupType string) (*NsxtFirewallGroup, error) { 163 queryParameters := url.Values{} 164 165 if firewallGroupType != "" { 166 queryParameters = queryParameterFilterAnd(fmt.Sprintf("typeValue==%s", firewallGroupType), queryParameters) 167 } 168 169 // Automatically inject Edge Gateway filter because this is an Edge Gateway scoped query 170 queryParameters = queryParameterFilterAnd("_context=="+egw.EdgeGateway.ID, queryParameters) 171 172 return getNsxtFirewallGroupByName(egw.client, name, queryParameters) 173 } 174 175 // GetNsxtFirewallGroupById retrieves NSX-T Firewall Group by ID 176 func (org *Org) GetNsxtFirewallGroupById(id string) (*NsxtFirewallGroup, error) { 177 return getNsxtFirewallGroupById(org.client, id) 178 } 179 180 // GetNsxtFirewallGroupById retrieves NSX-T Firewall Group by ID 181 func (vdc *Vdc) GetNsxtFirewallGroupById(id string) (*NsxtFirewallGroup, error) { 182 return getNsxtFirewallGroupById(vdc.client, id) 183 } 184 185 // GetNsxtFirewallGroupById retrieves NSX-T Firewall Group by ID 186 func (egw *NsxtEdgeGateway) GetNsxtFirewallGroupById(id string) (*NsxtFirewallGroup, error) { 187 return getNsxtFirewallGroupById(egw.client, id) 188 } 189 190 // GetNsxtFirewallGroupById retrieves NSX-T Firewall Group by ID 191 func (vdcGroup *VdcGroup) GetNsxtFirewallGroupById(id string) (*NsxtFirewallGroup, error) { 192 return getNsxtFirewallGroupById(vdcGroup.client, id) 193 } 194 195 // Update allows users to update NSX-T Firewall Group 196 func (firewallGroup *NsxtFirewallGroup) Update(firewallGroupConfig *types.NsxtFirewallGroup) (*NsxtFirewallGroup, error) { 197 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointFirewallGroups 198 apiVersion, err := firewallGroup.client.getOpenApiHighestElevatedVersion(endpoint) 199 if err != nil { 200 return nil, err 201 } 202 203 if firewallGroupConfig.ID == "" { 204 return nil, fmt.Errorf("cannot update NSX-T Firewall Group without ID") 205 } 206 207 urlRef, err := firewallGroup.client.OpenApiBuildEndpoint(endpoint, firewallGroupConfig.ID) 208 if err != nil { 209 return nil, err 210 } 211 212 returnObject := &NsxtFirewallGroup{ 213 NsxtFirewallGroup: &types.NsxtFirewallGroup{}, 214 client: firewallGroup.client, 215 } 216 217 err = firewallGroup.client.OpenApiPutItem(apiVersion, urlRef, nil, firewallGroupConfig, returnObject.NsxtFirewallGroup, nil) 218 if err != nil { 219 return nil, fmt.Errorf("error updating NSX-T firewall group: %s", err) 220 } 221 222 return returnObject, nil 223 } 224 225 // Delete allows users to delete NSX-T Firewall Group 226 func (firewallGroup *NsxtFirewallGroup) Delete() error { 227 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointFirewallGroups 228 apiVersion, err := firewallGroup.client.getOpenApiHighestElevatedVersion(endpoint) 229 if err != nil { 230 return err 231 } 232 233 if firewallGroup.NsxtFirewallGroup.ID == "" { 234 return fmt.Errorf("cannot delete NSX-T Firewall Group without ID") 235 } 236 237 urlRef, err := firewallGroup.client.OpenApiBuildEndpoint(endpoint, firewallGroup.NsxtFirewallGroup.ID) 238 if err != nil { 239 return err 240 } 241 242 err = firewallGroup.client.OpenApiDeleteItem(apiVersion, urlRef, nil, nil) 243 244 if err != nil { 245 return fmt.Errorf("error deleting NSX-T Firewall Group: %s", err) 246 } 247 248 return nil 249 } 250 251 // GetAssociatedVms allows users to retrieve a list of references to child VMs (with vApps when they exist). 252 // 253 // Note. Only Security Groups have associated VMs. Executing it on an IP Set will return an error 254 // similar to: "only Security Groups have associated VMs. This Firewall Group has type 'IP_SET'" 255 func (firewallGroup *NsxtFirewallGroup) GetAssociatedVms() ([]*types.NsxtFirewallGroupMemberVms, error) { 256 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointFirewallGroups 257 apiVersion, err := firewallGroup.client.getOpenApiHighestElevatedVersion(endpoint) 258 if err != nil { 259 return nil, err 260 } 261 262 if firewallGroup.NsxtFirewallGroup.ID == "" { 263 return nil, fmt.Errorf("cannot retrieve associated VMs for NSX-T Firewall Group without ID") 264 } 265 266 if !firewallGroup.IsSecurityGroup() && !firewallGroup.IsDynamicSecurityGroup() { 267 return nil, fmt.Errorf("only Security Groups have associated VMs. This Firewall Group has type '%s'", 268 firewallGroup.NsxtFirewallGroup.Type) 269 } 270 271 urlRef, err := firewallGroup.client.OpenApiBuildEndpoint(endpoint, firewallGroup.NsxtFirewallGroup.ID, "/associatedVMs") 272 if err != nil { 273 return nil, err 274 } 275 276 associatedVms := []*types.NsxtFirewallGroupMemberVms{{}} 277 278 err = firewallGroup.client.OpenApiGetAllItems(apiVersion, urlRef, nil, &associatedVms, nil) 279 280 if err != nil { 281 return nil, fmt.Errorf("error retrieving associated VMs: %s", err) 282 } 283 284 return associatedVms, nil 285 } 286 287 // IsSecurityGroup allows users to check if Firewall Group is a Static Security Group 288 func (firewallGroup *NsxtFirewallGroup) IsSecurityGroup() bool { 289 return firewallGroup.NsxtFirewallGroup.Type == types.FirewallGroupTypeSecurityGroup 290 } 291 292 // IsDynamicSecurityGroup allows users to check if Firewall Group is a Dynamic Security Group 293 func (firewallGroup *NsxtFirewallGroup) IsDynamicSecurityGroup() bool { 294 return firewallGroup.NsxtFirewallGroup.TypeValue == types.FirewallGroupTypeVmCriteria 295 } 296 297 // IsIpSet allows users to check if Firewall Group is an IP Set 298 func (firewallGroup *NsxtFirewallGroup) IsIpSet() bool { 299 return firewallGroup.NsxtFirewallGroup.Type == types.FirewallGroupTypeIpSet 300 } 301 302 func getNsxtFirewallGroupByName(client *Client, name string, queryParameters url.Values) (*NsxtFirewallGroup, error) { 303 queryParams := copyOrNewUrlValues(queryParameters) 304 queryParams = queryParameterFilterAnd("name=="+name, queryParams) 305 306 allGroups, err := getAllNsxtFirewallGroups(client, queryParams) 307 if err != nil { 308 return nil, fmt.Errorf("could not find NSX-T Firewall Group with name '%s': %s", name, err) 309 } 310 311 if len(allGroups) == 0 { 312 return nil, fmt.Errorf("%s: expected exactly one NSX-T Firewall Group with name '%s'. Got %d", ErrorEntityNotFound, name, len(allGroups)) 313 } 314 315 if len(allGroups) > 1 { 316 return nil, fmt.Errorf("expected exactly one NSX-T Firewall Group with name '%s'. Got %d", name, len(allGroups)) 317 } 318 319 // TODO API V36.0 - maybe it is fixed 320 // There is a bug that not all data is present (e.g. missing IpAddresses field for IP_SET) when 321 // using "getAll" endpoint therefore after finding the object by name we must retrieve it once 322 // again using its direct endpoint. 323 // 324 // return allGroups[0], nil 325 326 return getNsxtFirewallGroupById(client, allGroups[0].NsxtFirewallGroup.ID) 327 } 328 329 func getNsxtFirewallGroupById(client *Client, id string) (*NsxtFirewallGroup, error) { 330 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointFirewallGroups 331 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 332 if err != nil { 333 return nil, err 334 } 335 336 if id == "" { 337 return nil, fmt.Errorf("empty NSX-T Firewall Group ID specified") 338 } 339 340 urlRef, err := client.OpenApiBuildEndpoint(endpoint, id) 341 if err != nil { 342 return nil, err 343 } 344 345 fwGroup := &NsxtFirewallGroup{ 346 NsxtFirewallGroup: &types.NsxtFirewallGroup{}, 347 client: client, 348 } 349 350 err = client.OpenApiGetItem(apiVersion, urlRef, nil, fwGroup.NsxtFirewallGroup, nil) 351 if err != nil { 352 return nil, err 353 } 354 355 return fwGroup, nil 356 } 357 358 func getAllNsxtFirewallGroups(client *Client, queryParameters url.Values) ([]*NsxtFirewallGroup, error) { 359 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointFirewallGroups 360 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 361 if err != nil { 362 return nil, err 363 } 364 365 // This Object does not follow regular REST scheme and for get the endpoint must be 366 // 1.0.0/firewallGroups/summaries therefore bellow "summaries" is appended to the path 367 urlRef, err := client.OpenApiBuildEndpoint(endpoint, "summaries") 368 if err != nil { 369 return nil, err 370 } 371 372 typeResponses := []*types.NsxtFirewallGroup{{}} 373 err = client.OpenApiGetAllItems(apiVersion, urlRef, queryParameters, &typeResponses, nil) 374 if err != nil { 375 return nil, err 376 } 377 378 // Wrap all typeResponses into NsxtEdgeGateway types with client 379 wrappedResponses := make([]*NsxtFirewallGroup, len(typeResponses)) 380 for sliceIndex := range typeResponses { 381 wrappedResponses[sliceIndex] = &NsxtFirewallGroup{ 382 NsxtFirewallGroup: typeResponses[sliceIndex], 383 client: client, 384 } 385 } 386 387 return wrappedResponses, nil 388 } 389 390 func createNsxtFirewallGroup(client *Client, firewallGroupConfig *types.NsxtFirewallGroup) (*NsxtFirewallGroup, error) { 391 endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointFirewallGroups 392 apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint) 393 if err != nil { 394 return nil, err 395 } 396 397 urlRef, err := client.OpenApiBuildEndpoint(endpoint) 398 if err != nil { 399 return nil, err 400 } 401 402 returnObject := &NsxtFirewallGroup{ 403 NsxtFirewallGroup: &types.NsxtFirewallGroup{}, 404 client: client, 405 } 406 407 err = client.OpenApiPostItem(apiVersion, urlRef, nil, firewallGroupConfig, returnObject.NsxtFirewallGroup, nil) 408 if err != nil { 409 return nil, fmt.Errorf("error creating NSX-T Firewall Group: %s", err) 410 } 411 412 return returnObject, nil 413 }