Merge pull request #15570 from hakman/azure_network_security

azure: Add support for network security groups
This commit is contained in:
Kubernetes Prow Robot 2023-07-01 06:54:48 -07:00 committed by GitHub
commit 49a6ed4188
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 629 additions and 62 deletions

View File

@ -17,8 +17,12 @@ limitations under the License.
package azuremodel package azuremodel
import ( import (
"fmt"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2022-05-01/network"
"k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/azuretasks" "k8s.io/kops/upup/pkg/fi/cloudup/azuretasks"
"k8s.io/utils/net"
) )
// NetworkModelBuilder configures a Virtual Network and subnets. // NetworkModelBuilder configures a Virtual Network and subnets.
@ -41,14 +45,134 @@ func (b *NetworkModelBuilder) Build(c *fi.CloudupModelBuilderContext) error {
} }
c.AddTask(networkTask) c.AddTask(networkTask)
nsgTask := &azuretasks.NetworkSecurityGroup{
Name: fi.PtrTo(b.NameForVirtualNetwork()),
Lifecycle: b.Lifecycle,
ResourceGroup: b.LinkToResourceGroup(),
Tags: map[string]*string{},
}
var sshAccessIPv4, sshAccessIPv6 []string
for _, cidr := range b.Cluster.Spec.SSHAccess {
switch net.IPFamilyOfCIDRString(cidr) {
case net.IPv4:
sshAccessIPv4 = append(sshAccessIPv4, cidr)
case net.IPv6:
sshAccessIPv6 = append(sshAccessIPv6, cidr)
default:
return fmt.Errorf("unknown IP family for CIDR: %q", cidr)
}
}
if len(sshAccessIPv4) > 0 {
nsgTask.SecurityRules = append(nsgTask.SecurityRules, &azuretasks.NetworkSecurityRule{
Name: fi.PtrTo("AllowSSH"),
Priority: fi.PtrTo[int32](100),
Access: network.SecurityRuleAccessAllow,
Direction: network.SecurityRuleDirectionInbound,
Protocol: network.SecurityRuleProtocolTCP,
SourceAddressPrefixes: &sshAccessIPv4,
SourcePortRange: fi.PtrTo("*"),
DestinationAddressPrefix: fi.PtrTo("*"),
DestinationPortRange: fi.PtrTo("22"),
})
}
if len(sshAccessIPv6) > 0 {
nsgTask.SecurityRules = append(nsgTask.SecurityRules, &azuretasks.NetworkSecurityRule{
Name: fi.PtrTo("AllowSSH_v6"),
Priority: fi.PtrTo[int32](101),
Access: network.SecurityRuleAccessAllow,
Direction: network.SecurityRuleDirectionInbound,
Protocol: network.SecurityRuleProtocolTCP,
SourceAddressPrefixes: &sshAccessIPv6,
SourcePortRange: fi.PtrTo("*"),
DestinationAddressPrefix: fi.PtrTo("*"),
DestinationPortRange: fi.PtrTo("22"),
})
}
var k8sAccessIPv4, k8sAccessIPv6 []string
for _, cidr := range b.Cluster.Spec.API.Access {
switch net.IPFamilyOfCIDRString(cidr) {
case net.IPv4:
k8sAccessIPv4 = append(k8sAccessIPv4, cidr)
case net.IPv6:
k8sAccessIPv6 = append(k8sAccessIPv6, cidr)
default:
return fmt.Errorf("unknown IP family for CIDR: %q", cidr)
}
}
if len(k8sAccessIPv4) > 0 {
nsgTask.SecurityRules = append(nsgTask.SecurityRules, &azuretasks.NetworkSecurityRule{
Name: fi.PtrTo("AllowKubernetesAPI"),
Priority: fi.PtrTo[int32](200),
Access: network.SecurityRuleAccessAllow,
Direction: network.SecurityRuleDirectionInbound,
Protocol: network.SecurityRuleProtocolTCP,
SourceAddressPrefixes: &k8sAccessIPv4,
SourcePortRange: fi.PtrTo("*"),
DestinationAddressPrefix: fi.PtrTo("*"),
DestinationPortRange: fi.PtrTo("443"),
})
}
if len(k8sAccessIPv6) > 0 {
nsgTask.SecurityRules = append(nsgTask.SecurityRules, &azuretasks.NetworkSecurityRule{
Name: fi.PtrTo("AllowKubernetesAPI_v6"),
Priority: fi.PtrTo[int32](201),
Access: network.SecurityRuleAccessAllow,
Direction: network.SecurityRuleDirectionInbound,
Protocol: network.SecurityRuleProtocolTCP,
SourceAddressPrefixes: &k8sAccessIPv6,
SourcePortRange: fi.PtrTo("*"),
DestinationAddressPrefix: fi.PtrTo("*"),
DestinationPortRange: fi.PtrTo("443"),
})
}
var nodePortAccessIPv4, nodePortAccessIPv6 []string
for _, cidr := range b.Cluster.Spec.NodePortAccess {
switch net.IPFamilyOfCIDRString(cidr) {
case net.IPv4:
nodePortAccessIPv4 = append(nodePortAccessIPv4, cidr)
case net.IPv6:
nodePortAccessIPv6 = append(nodePortAccessIPv6, cidr)
default:
return fmt.Errorf("unknown IP family for CIDR: %q", cidr)
}
}
if len(nodePortAccessIPv4) > 0 {
nsgTask.SecurityRules = append(nsgTask.SecurityRules, &azuretasks.NetworkSecurityRule{
Name: fi.PtrTo("AllowNodePort"),
Priority: fi.PtrTo[int32](300),
Access: network.SecurityRuleAccessAllow,
Direction: network.SecurityRuleDirectionInbound,
Protocol: network.SecurityRuleProtocolTCP,
SourceAddressPrefixes: &nodePortAccessIPv4,
SourcePortRange: fi.PtrTo("*"),
DestinationAddressPrefix: fi.PtrTo("*"),
DestinationPortRange: fi.PtrTo("443"),
})
}
if len(nodePortAccessIPv6) > 0 {
nsgTask.SecurityRules = append(nsgTask.SecurityRules, &azuretasks.NetworkSecurityRule{
Name: fi.PtrTo("AllowNodePort_v6"),
Priority: fi.PtrTo[int32](301),
Access: network.SecurityRuleAccessAllow,
Direction: network.SecurityRuleDirectionInbound,
Protocol: network.SecurityRuleProtocolTCP,
SourceAddressPrefixes: &nodePortAccessIPv6,
SourcePortRange: fi.PtrTo("*"),
DestinationAddressPrefix: fi.PtrTo("*"),
DestinationPortRange: fi.PtrTo("443"),
})
}
c.AddTask(nsgTask)
for _, subnetSpec := range b.Cluster.Spec.Networking.Subnets { for _, subnetSpec := range b.Cluster.Spec.Networking.Subnets {
subnetTask := &azuretasks.Subnet{ subnetTask := &azuretasks.Subnet{
Name: fi.PtrTo(subnetSpec.Name), Name: fi.PtrTo(subnetSpec.Name),
Lifecycle: b.Lifecycle, Lifecycle: b.Lifecycle,
ResourceGroup: b.LinkToResourceGroup(), ResourceGroup: b.LinkToResourceGroup(),
VirtualNetwork: b.LinkToVirtualNetwork(), VirtualNetwork: b.LinkToVirtualNetwork(),
CIDR: fi.PtrTo(subnetSpec.CIDR), NetworkSecurityGroup: nsgTask,
Shared: fi.PtrTo(b.Cluster.SharedVPC()), CIDR: fi.PtrTo(subnetSpec.CIDR),
Shared: fi.PtrTo(b.Cluster.SharedVPC()),
} }
c.AddTask(subnetTask) c.AddTask(subnetTask)
} }

View File

@ -31,15 +31,16 @@ import (
) )
const ( const (
typeResourceGroup = "ResourceGroup" typeResourceGroup = "ResourceGroup"
typeVirtualNetwork = "VirtualNetwork" typeVirtualNetwork = "VirtualNetwork"
typeSubnet = "Subnet" typeNetworkSecurityGroup = "NetworkSecurityGroup"
typeRouteTable = "RouteTable" typeSubnet = "Subnet"
typeVMScaleSet = "VMScaleSet" typeRouteTable = "RouteTable"
typeDisk = "Disk" typeVMScaleSet = "VMScaleSet"
typeRoleAssignment = "RoleAssignment" typeDisk = "Disk"
typeLoadBalancer = "LoadBalancer" typeRoleAssignment = "RoleAssignment"
typePublicIPAddress = "PublicIPAddress" typeLoadBalancer = "LoadBalancer"
typePublicIPAddress = "PublicIPAddress"
) )
// ListResourcesAzure lists all resources for the cluster by quering Azure. // ListResourcesAzure lists all resources for the cluster by quering Azure.
@ -85,6 +86,7 @@ func (g *resourceGetter) listAll() ([]*resources.Resource, error) {
fns := []func(ctx context.Context) ([]*resources.Resource, error){ fns := []func(ctx context.Context) ([]*resources.Resource, error){
g.listResourceGroups, g.listResourceGroups,
g.listVirtualNetworksAndSubnets, g.listVirtualNetworksAndSubnets,
g.listNetworkSecurityGroups,
g.listRouteTables, g.listRouteTables,
g.listVMScaleSetsAndRoleAssignments, g.listVMScaleSetsAndRoleAssignments,
g.listDisks, g.listDisks,
@ -209,6 +211,39 @@ func (g *resourceGetter) deleteSubnet(vnetName string, r *resources.Resource) er
return g.cloud.Subnet().Delete(context.TODO(), g.resourceGroupName(), vnetName, r.Name) return g.cloud.Subnet().Delete(context.TODO(), g.resourceGroupName(), vnetName, r.Name)
} }
func (g *resourceGetter) listNetworkSecurityGroups(ctx context.Context) ([]*resources.Resource, error) {
NetworkSecurityGroups, err := g.cloud.NetworkSecurityGroup().List(ctx, g.resourceGroupName())
if err != nil {
return nil, err
}
var rs []*resources.Resource
for i := range NetworkSecurityGroups {
rs = append(rs, g.toNetworkSecurityGroupResource(&NetworkSecurityGroups[i]))
}
return rs, nil
}
func (g *resourceGetter) toNetworkSecurityGroupResource(NetworkSecurityGroup *network.SecurityGroup) *resources.Resource {
return &resources.Resource{
Obj: NetworkSecurityGroup,
Type: typeNetworkSecurityGroup,
ID: *NetworkSecurityGroup.Name,
Name: *NetworkSecurityGroup.Name,
Deleter: func(_ fi.Cloud, r *resources.Resource) error {
return g.deleteNetworkSecurityGroup(r)
},
Blocks: []string{
toKey(typeResourceGroup, g.resourceGroupName()),
},
Shared: g.clusterInfo.AzureNetworkShared,
}
}
func (g *resourceGetter) deleteNetworkSecurityGroup(r *resources.Resource) error {
return g.cloud.NetworkSecurityGroup().Delete(context.TODO(), g.resourceGroupName(), r.Name)
}
func (g *resourceGetter) listRouteTables(ctx context.Context) ([]*resources.Resource, error) { func (g *resourceGetter) listRouteTables(ctx context.Context) ([]*resources.Resource, error) {
rts, err := g.cloud.RouteTable().List(ctx, g.resourceGroupName()) rts, err := g.cloud.RouteTable().List(ctx, g.resourceGroupName())
if err != nil { if err != nil {

View File

@ -49,6 +49,7 @@ type AzureCloud interface {
VirtualNetwork() VirtualNetworksClient VirtualNetwork() VirtualNetworksClient
Subnet() SubnetsClient Subnet() SubnetsClient
RouteTable() RouteTablesClient RouteTable() RouteTablesClient
NetworkSecurityGroup() NetworkSecurityGroupsClient
VMScaleSet() VMScaleSetsClient VMScaleSet() VMScaleSetsClient
VMScaleSetVM() VMScaleSetVMsClient VMScaleSetVM() VMScaleSetVMsClient
Disk() DisksClient Disk() DisksClient
@ -59,20 +60,21 @@ type AzureCloud interface {
} }
type azureCloudImplementation struct { type azureCloudImplementation struct {
subscriptionID string subscriptionID string
location string location string
tags map[string]string tags map[string]string
resourceGroupsClient ResourceGroupsClient resourceGroupsClient ResourceGroupsClient
vnetsClient VirtualNetworksClient networkSecurityGroupsClient NetworkSecurityGroupsClient
subnetsClient SubnetsClient vnetsClient VirtualNetworksClient
routeTablesClient RouteTablesClient subnetsClient SubnetsClient
vmscaleSetsClient VMScaleSetsClient routeTablesClient RouteTablesClient
vmscaleSetVMsClient VMScaleSetVMsClient vmscaleSetsClient VMScaleSetsClient
disksClient DisksClient vmscaleSetVMsClient VMScaleSetVMsClient
roleAssignmentsClient RoleAssignmentsClient disksClient DisksClient
networkInterfacesClient NetworkInterfacesClient roleAssignmentsClient RoleAssignmentsClient
loadBalancersClient LoadBalancersClient networkInterfacesClient NetworkInterfacesClient
publicIPAddressesClient PublicIPAddressesClient loadBalancersClient LoadBalancersClient
publicIPAddressesClient PublicIPAddressesClient
} }
var _ fi.Cloud = &azureCloudImplementation{} var _ fi.Cloud = &azureCloudImplementation{}
@ -85,20 +87,21 @@ func NewAzureCloud(subscriptionID, location string, tags map[string]string) (Azu
} }
return &azureCloudImplementation{ return &azureCloudImplementation{
subscriptionID: subscriptionID, subscriptionID: subscriptionID,
location: location, location: location,
tags: tags, tags: tags,
resourceGroupsClient: newResourceGroupsClientImpl(subscriptionID, authorizer), resourceGroupsClient: newResourceGroupsClientImpl(subscriptionID, authorizer),
vnetsClient: newVirtualNetworksClientImpl(subscriptionID, authorizer), vnetsClient: newVirtualNetworksClientImpl(subscriptionID, authorizer),
subnetsClient: newSubnetsClientImpl(subscriptionID, authorizer), subnetsClient: newSubnetsClientImpl(subscriptionID, authorizer),
routeTablesClient: newRouteTablesClientImpl(subscriptionID, authorizer), routeTablesClient: newRouteTablesClientImpl(subscriptionID, authorizer),
vmscaleSetsClient: newVMScaleSetsClientImpl(subscriptionID, authorizer), networkSecurityGroupsClient: newNetworkSecurityGroupsClientImpl(subscriptionID, authorizer),
vmscaleSetVMsClient: newVMScaleSetVMsClientImpl(subscriptionID, authorizer), vmscaleSetsClient: newVMScaleSetsClientImpl(subscriptionID, authorizer),
disksClient: newDisksClientImpl(subscriptionID, authorizer), vmscaleSetVMsClient: newVMScaleSetVMsClientImpl(subscriptionID, authorizer),
roleAssignmentsClient: newRoleAssignmentsClientImpl(subscriptionID, authorizer), disksClient: newDisksClientImpl(subscriptionID, authorizer),
networkInterfacesClient: newNetworkInterfacesClientImpl(subscriptionID, authorizer), roleAssignmentsClient: newRoleAssignmentsClientImpl(subscriptionID, authorizer),
loadBalancersClient: newLoadBalancersClientImpl(subscriptionID, authorizer), networkInterfacesClient: newNetworkInterfacesClientImpl(subscriptionID, authorizer),
publicIPAddressesClient: newPublicIPAddressesClientImpl(subscriptionID, authorizer), loadBalancersClient: newLoadBalancersClientImpl(subscriptionID, authorizer),
publicIPAddressesClient: newPublicIPAddressesClientImpl(subscriptionID, authorizer),
}, nil }, nil
} }
@ -286,6 +289,10 @@ func (c *azureCloudImplementation) RouteTable() RouteTablesClient {
return c.routeTablesClient return c.routeTablesClient
} }
func (c *azureCloudImplementation) NetworkSecurityGroup() NetworkSecurityGroupsClient {
return c.networkSecurityGroupsClient
}
func (c *azureCloudImplementation) VMScaleSet() VMScaleSetsClient { func (c *azureCloudImplementation) VMScaleSet() VMScaleSetsClient {
return c.vmscaleSetsClient return c.vmscaleSetsClient
} }

View File

@ -0,0 +1,83 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package azure
import (
"context"
"fmt"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2022-05-01/network"
"github.com/Azure/go-autorest/autorest"
)
// NetworkSecurityGroupsClient is a client for managing Network Security Groups.
type NetworkSecurityGroupsClient interface {
CreateOrUpdate(ctx context.Context, resourceGroupName, NetworkSecurityGroupName string, parameters network.SecurityGroup) (*network.SecurityGroup, error)
List(ctx context.Context, resourceGroupName string) ([]network.SecurityGroup, error)
Delete(ctx context.Context, resourceGroupName, NetworkSecurityGroupName string) error
}
type NetworkSecurityGroupsClientImpl struct {
c *network.SecurityGroupsClient
}
var _ NetworkSecurityGroupsClient = &NetworkSecurityGroupsClientImpl{}
func (c *NetworkSecurityGroupsClientImpl) CreateOrUpdate(ctx context.Context, resourceGroupName, NetworkSecurityGroupName string, parameters network.SecurityGroup) (*network.SecurityGroup, error) {
future, err := c.c.CreateOrUpdate(ctx, resourceGroupName, NetworkSecurityGroupName, parameters)
if err != nil {
return nil, fmt.Errorf("error creating/updating Network Security Group: %w", err)
}
if err := future.WaitForCompletionRef(ctx, c.c.Client); err != nil {
return nil, fmt.Errorf("error waiting for Network Security Group create/update completion: %w", err)
}
asg, err := future.Result(*c.c)
if err != nil {
return nil, fmt.Errorf("error obtaining result for Network Security Group create/update: %w", err)
}
return &asg, err
}
func (c *NetworkSecurityGroupsClientImpl) List(ctx context.Context, resourceGroupName string) ([]network.SecurityGroup, error) {
var l []network.SecurityGroup
for iter, err := c.c.ListComplete(ctx, resourceGroupName); iter.NotDone(); err = iter.NextWithContext(ctx) {
if err != nil {
return nil, err
}
l = append(l, iter.Value())
}
return l, nil
}
func (c *NetworkSecurityGroupsClientImpl) Delete(ctx context.Context, resourceGroupName, NetworkSecurityGroupName string) error {
future, err := c.c.Delete(ctx, resourceGroupName, NetworkSecurityGroupName)
if err != nil {
return fmt.Errorf("error deleting Network Security Group: %w", err)
}
if err := future.WaitForCompletionRef(ctx, c.c.Client); err != nil {
return fmt.Errorf("error waiting for Network Security Group deletion completion: %w", err)
}
return nil
}
func newNetworkSecurityGroupsClientImpl(subscriptionID string, authorizer autorest.Authorizer) *NetworkSecurityGroupsClientImpl {
c := network.NewSecurityGroupsClient(subscriptionID)
c.Authorizer = authorizer
return &NetworkSecurityGroupsClientImpl{
c: &c,
}
}

View File

@ -0,0 +1,197 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package azuretasks
import (
"context"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2022-05-01/network"
"github.com/Azure/go-autorest/autorest/to"
"k8s.io/klog/v2"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/azure"
)
// NetworkSecurityGroup is an Azure Cloud Network Security Group
// +kops:fitask
type NetworkSecurityGroup struct {
Name *string
ID *string
Lifecycle fi.Lifecycle
ResourceGroup *ResourceGroup
SecurityRules []*NetworkSecurityRule
Tags map[string]*string
}
var (
_ fi.CloudupTask = &NetworkSecurityGroup{}
_ fi.CompareWithID = &NetworkSecurityGroup{}
_ fi.CloudupTaskNormalize = &NetworkSecurityGroup{}
)
// CompareWithID returns the Name of the Network Security Group
func (nsg *NetworkSecurityGroup) CompareWithID() *string {
return nsg.ID
}
// Find discovers the Network Security Group in the cloud provider
func (nsg *NetworkSecurityGroup) Find(c *fi.CloudupContext) (*NetworkSecurityGroup, error) {
cloud := c.T.Cloud.(azure.AzureCloud)
l, err := cloud.NetworkSecurityGroup().List(context.TODO(), *nsg.ResourceGroup.Name)
if err != nil {
return nil, err
}
var found *network.SecurityGroup
for _, v := range l {
if *v.Name == *nsg.Name {
found = &v
break
}
}
if found == nil {
return nil, nil
}
actual := &NetworkSecurityGroup{
Name: nsg.Name,
Lifecycle: nsg.Lifecycle,
ResourceGroup: &ResourceGroup{
Name: nsg.ResourceGroup.Name,
},
ID: found.ID,
Tags: found.Tags,
}
for _, rule := range *found.SecurityRules {
nsr := &NetworkSecurityRule{
Name: rule.Name,
Priority: rule.Priority,
Access: rule.Access,
Direction: rule.Direction,
Protocol: rule.Protocol,
SourceAddressPrefix: rule.SourceAddressPrefix,
SourceAddressPrefixes: rule.SourceAddressPrefixes,
SourcePortRange: rule.SourcePortRange,
DestinationAddressPrefix: rule.DestinationAddressPrefix,
DestinationAddressPrefixes: rule.DestinationAddressPrefixes,
DestinationPortRange: rule.DestinationPortRange,
}
actual.SecurityRules = append(actual.SecurityRules, nsr)
}
nsg.ID = found.ID
return actual, nil
}
func (nsg *NetworkSecurityGroup) Normalize(c *fi.CloudupContext) error {
c.T.Cloud.(azure.AzureCloud).AddClusterTags(nsg.Tags)
return nil
}
// Run implements fi.Task.Run.
func (nsg *NetworkSecurityGroup) Run(c *fi.CloudupContext) error {
return fi.CloudupDefaultDeltaRunMethod(nsg, c)
}
// CheckChanges returns an error if a change is not allowed.
func (*NetworkSecurityGroup) CheckChanges(a, e, changes *NetworkSecurityGroup) error {
if a == nil {
// Check if required fields are set when a new resource is created.
if e.Name == nil {
return fi.RequiredField("Name")
}
return nil
}
// Check if unchangeable fields won't be changed.
if changes.Name != nil {
return fi.CannotChangeField("Name")
}
return nil
}
// RenderAzure creates or updates a Network Security Group.
func (*NetworkSecurityGroup) RenderAzure(t *azure.AzureAPITarget, a, e, changes *NetworkSecurityGroup) error {
if a == nil {
klog.Infof("Creating a new Network Security Group with name: %s", fi.ValueOf(e.Name))
} else {
klog.Infof("Updating a Network Security Group with name: %s", fi.ValueOf(e.Name))
}
p := network.SecurityGroup{
SecurityGroupPropertiesFormat: &network.SecurityGroupPropertiesFormat{
SecurityRules: &[]network.SecurityRule{},
},
Location: to.StringPtr(t.Cloud.Region()),
Name: to.StringPtr(*e.Name),
Tags: e.Tags,
}
for _, nsr := range e.SecurityRules {
securityRule := network.SecurityRule{
Name: nsr.Name,
SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{
Priority: nsr.Priority,
Access: nsr.Access,
Direction: nsr.Direction,
Protocol: nsr.Protocol,
SourceAddressPrefix: nsr.SourceAddressPrefix,
SourceAddressPrefixes: nsr.SourceAddressPrefixes,
SourcePortRange: nsr.SourcePortRange,
DestinationAddressPrefix: nsr.DestinationAddressPrefix,
DestinationAddressPrefixes: nsr.DestinationAddressPrefixes,
DestinationPortRange: nsr.DestinationPortRange,
},
}
*p.SecurityRules = append(*p.SecurityRules, securityRule)
}
nsg, err := t.Cloud.NetworkSecurityGroup().CreateOrUpdate(
context.TODO(),
*e.ResourceGroup.Name,
*e.Name,
p)
if err != nil {
return err
}
e.ID = nsg.ID
return nil
}
// NetworkSecurityRule represents a NetworkSecurityGroup rule.
type NetworkSecurityRule struct {
Name *string
Priority *int32
Access network.SecurityRuleAccess
Direction network.SecurityRuleDirection
Protocol network.SecurityRuleProtocol
SourceAddressPrefix *string
SourceAddressPrefixes *[]string
SourcePortRange *string
DestinationAddressPrefixes *[]string
DestinationAddressPrefix *string
DestinationPortRange *string
}
var _ fi.CloudupHasDependencies = &NetworkSecurityRule{}
func (e *NetworkSecurityRule) GetDependencies(tasks map[string]fi.CloudupTask) []fi.CloudupTask {
return nil
}

View File

@ -0,0 +1,52 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by fitask. DO NOT EDIT.
package azuretasks
import (
"k8s.io/kops/upup/pkg/fi"
)
// NetworkSecurityGroup
var _ fi.HasLifecycle = &NetworkSecurityGroup{}
// GetLifecycle returns the Lifecycle of the object, implementing fi.HasLifecycle
func (o *NetworkSecurityGroup) GetLifecycle() fi.Lifecycle {
return o.Lifecycle
}
// SetLifecycle sets the Lifecycle of the object, implementing fi.SetLifecycle
func (o *NetworkSecurityGroup) SetLifecycle(lifecycle fi.Lifecycle) {
o.Lifecycle = lifecycle
}
var _ fi.HasName = &NetworkSecurityGroup{}
// GetName returns the Name of the object, implementing fi.HasName
func (o *NetworkSecurityGroup) GetName() *string {
return o.Name
}
// String is the stringer function for the task, producing readable output using fi.TaskAsString
func (o *NetworkSecurityGroup) String() string {
return fi.CloudupTaskAsString(o)
}

View File

@ -31,10 +31,12 @@ type Subnet struct {
Name *string Name *string
Lifecycle fi.Lifecycle Lifecycle fi.Lifecycle
ResourceGroup *ResourceGroup ResourceGroup *ResourceGroup
VirtualNetwork *VirtualNetwork VirtualNetwork *VirtualNetwork
CIDR *string NetworkSecurityGroup *NetworkSecurityGroup
Shared *bool
CIDR *string
Shared *bool
} }
var ( var (
@ -65,7 +67,7 @@ func (s *Subnet) Find(c *fi.CloudupContext) (*Subnet, error) {
return nil, nil return nil, nil
} }
return &Subnet{ fs := &Subnet{
Name: s.Name, Name: s.Name,
Lifecycle: s.Lifecycle, Lifecycle: s.Lifecycle,
Shared: s.Shared, Shared: s.Shared,
@ -76,7 +78,14 @@ func (s *Subnet) Find(c *fi.CloudupContext) (*Subnet, error) {
Name: s.VirtualNetwork.Name, Name: s.VirtualNetwork.Name,
}, },
CIDR: found.AddressPrefix, CIDR: found.AddressPrefix,
}, nil }
if found.NetworkSecurityGroup != nil {
fs.NetworkSecurityGroup = &NetworkSecurityGroup{
ID: found.NetworkSecurityGroup.ID,
}
}
return fs, nil
} }
// Run implements fi.Task.Run. // Run implements fi.Task.Run.
@ -109,12 +118,17 @@ func (*Subnet) RenderAzure(t *azure.AzureAPITarget, a, e, changes *Subnet) error
klog.Infof("Updating a Subnet with name: %s", fi.ValueOf(e.Name)) klog.Infof("Updating a Subnet with name: %s", fi.ValueOf(e.Name))
} }
// TODO(kenji): Be able to specify security groups.
subnet := network.Subnet{ subnet := network.Subnet{
SubnetPropertiesFormat: &network.SubnetPropertiesFormat{ SubnetPropertiesFormat: &network.SubnetPropertiesFormat{
AddressPrefix: e.CIDR, AddressPrefix: e.CIDR,
}, },
} }
if e.NetworkSecurityGroup != nil {
subnet.NetworkSecurityGroup = &network.SecurityGroup{
ID: e.NetworkSecurityGroup.ID,
}
}
return t.Cloud.Subnet().CreateOrUpdate( return t.Cloud.Subnet().CreateOrUpdate(
context.TODO(), context.TODO(),
*e.ResourceGroup.Name, *e.ResourceGroup.Name,

View File

@ -46,18 +46,19 @@ const (
// MockAzureCloud is a mock implementation of AzureCloud. // MockAzureCloud is a mock implementation of AzureCloud.
type MockAzureCloud struct { type MockAzureCloud struct {
Location string Location string
ResourceGroupsClient *MockResourceGroupsClient ResourceGroupsClient *MockResourceGroupsClient
VirtualNetworksClient *MockVirtualNetworksClient VirtualNetworksClient *MockVirtualNetworksClient
SubnetsClient *MockSubnetsClient SubnetsClient *MockSubnetsClient
RouteTablesClient *MockRouteTablesClient RouteTablesClient *MockRouteTablesClient
VMScaleSetsClient *MockVMScaleSetsClient NetworkSecurityGroupsClient *MockNetworkSecurityGroupsClient
VMScaleSetVMsClient *MockVMScaleSetVMsClient VMScaleSetsClient *MockVMScaleSetsClient
DisksClient *MockDisksClient VMScaleSetVMsClient *MockVMScaleSetVMsClient
RoleAssignmentsClient *MockRoleAssignmentsClient DisksClient *MockDisksClient
NetworkInterfacesClient *MockNetworkInterfacesClient RoleAssignmentsClient *MockRoleAssignmentsClient
LoadBalancersClient *MockLoadBalancersClient NetworkInterfacesClient *MockNetworkInterfacesClient
PublicIPAddressesClient *MockPublicIPAddressesClient LoadBalancersClient *MockLoadBalancersClient
PublicIPAddressesClient *MockPublicIPAddressesClient
} }
var _ azure.AzureCloud = &MockAzureCloud{} var _ azure.AzureCloud = &MockAzureCloud{}
@ -78,6 +79,9 @@ func NewMockAzureCloud(location string) *MockAzureCloud {
RouteTablesClient: &MockRouteTablesClient{ RouteTablesClient: &MockRouteTablesClient{
RTs: map[string]network.RouteTable{}, RTs: map[string]network.RouteTable{},
}, },
NetworkSecurityGroupsClient: &MockNetworkSecurityGroupsClient{
NSGs: map[string]network.SecurityGroup{},
},
VMScaleSetsClient: &MockVMScaleSetsClient{ VMScaleSetsClient: &MockVMScaleSetsClient{
VMSSes: map[string]compute.VirtualMachineScaleSet{}, VMSSes: map[string]compute.VirtualMachineScaleSet{},
}, },
@ -195,6 +199,11 @@ func (c *MockAzureCloud) RouteTable() azure.RouteTablesClient {
return c.RouteTablesClient return c.RouteTablesClient
} }
// NetworkSecurityGroup returns the VM Scale Set client.
func (c *MockAzureCloud) NetworkSecurityGroup() azure.NetworkSecurityGroupsClient {
return c.NetworkSecurityGroupsClient
}
// VMScaleSet returns the VM Scale Set client. // VMScaleSet returns the VM Scale Set client.
func (c *MockAzureCloud) VMScaleSet() azure.VMScaleSetsClient { func (c *MockAzureCloud) VMScaleSet() azure.VMScaleSetsClient {
return c.VMScaleSetsClient return c.VMScaleSetsClient
@ -612,3 +621,49 @@ func (c *MockPublicIPAddressesClient) Delete(ctx context.Context, scope, publicI
delete(c.PubIPs, publicIPAddressName) delete(c.PubIPs, publicIPAddressName)
return nil return nil
} }
// MockNetworkSecurityGroupsClient is a mock implementation of Network Security Group client.
type MockNetworkSecurityGroupsClient struct {
NSGs map[string]network.SecurityGroup
}
var _ azure.NetworkSecurityGroupsClient = &MockNetworkSecurityGroupsClient{}
// CreateOrUpdate creates or updates a Network Security Group.
func (c *MockNetworkSecurityGroupsClient) CreateOrUpdate(ctx context.Context, resourceGroupName, asgName string, parameters network.SecurityGroup) (*network.SecurityGroup, error) {
// Ignore resourceGroupName for simplicity.
if _, ok := c.NSGs[asgName]; ok {
return nil, fmt.Errorf("update not supported")
}
parameters.Name = &asgName
c.NSGs[asgName] = parameters
return &parameters, nil
}
// List returns a slice of Network Security Groups.
func (c *MockNetworkSecurityGroupsClient) List(ctx context.Context, resourceGroupName string) ([]network.SecurityGroup, error) {
var l []network.SecurityGroup
for _, nsg := range c.NSGs {
l = append(l, nsg)
}
return l, nil
}
// Get Returns a specified Network Security Group.
func (c *MockNetworkSecurityGroupsClient) Get(ctx context.Context, resourceGroupName string, nsgName string) (*network.SecurityGroup, error) {
asg, ok := c.NSGs[nsgName]
if !ok {
return nil, nil
}
return &asg, nil
}
// Delete deletes a specified Network Security Group.
func (c *MockNetworkSecurityGroupsClient) Delete(ctx context.Context, resourceGroupName, nsgName string) error {
// Ignore resourceGroupName for simplicity.
if _, ok := c.NSGs[nsgName]; !ok {
return fmt.Errorf("%s does not exist", nsgName)
}
delete(c.NSGs, nsgName)
return nil
}