constellation/cli/gcp/client/network.go
Leonard Cohnen 2d8fcd9bf4 monorepo
Co-authored-by: Malte Poll <mp@edgeless.systems>
Co-authored-by: katexochen <katexochen@users.noreply.github.com>
Co-authored-by: Daniel Weiße <dw@edgeless.systems>
Co-authored-by: Thomas Tendyck <tt@edgeless.systems>
Co-authored-by: Benedict Schlueter <bs@edgeless.systems>
Co-authored-by: leongross <leon.gross@rub.de>
Co-authored-by: Moritz Eckert <m1gh7ym0@gmail.com>
2022-03-22 16:09:39 +01:00

203 lines
5.2 KiB
Go

package client
import (
"context"
"errors"
"github.com/edgelesssys/constellation/cli/cloud/cloudtypes"
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
"google.golang.org/protobuf/proto"
)
// CreateFirewall creates a set of firewall rules for the client's network.
//
// The client must have a VPC network to set firewall rules.
func (c *Client) CreateFirewall(ctx context.Context, input FirewallInput) error {
if c.network == "" {
return errors.New("client has not network")
}
firewallRules := input.Ingress.GCP()
var ops []Operation
for _, rule := range firewallRules {
c.firewalls = append(c.firewalls, rule.GetName())
rule.Network = proto.String("global/networks/" + c.network)
rule.Name = proto.String(rule.GetName() + "-" + c.uid)
req := &computepb.InsertFirewallRequest{
FirewallResource: rule,
Project: c.project,
}
resp, err := c.firewallsAPI.Insert(ctx, req)
if err != nil {
return err
}
if resp.Proto().Name == nil {
return errors.New("operation name is nil")
}
ops = append(ops, resp)
}
return c.waitForOperations(ctx, ops)
}
// TerminateFirewall deletes firewall rules from the client's network.
//
// The client must have a VPC network to set firewall rules.
func (c *Client) TerminateFirewall(ctx context.Context) error {
if len(c.firewalls) == 0 {
return nil
}
var ops []Operation
for _, name := range c.firewalls {
ruleName := name + "-" + c.uid
req := &computepb.DeleteFirewallRequest{
Firewall: ruleName,
Project: c.project,
}
resp, err := c.firewallsAPI.Delete(ctx, req)
if err != nil {
return err
}
if resp.Proto().Name == nil {
return errors.New("operation name is nil")
}
ops = append(ops, resp)
}
if err := c.waitForOperations(ctx, ops); err != nil {
return err
}
c.firewalls = []string{}
return nil
}
// FirewallInput defines firewall rules to be set.
type FirewallInput struct {
Ingress cloudtypes.Firewall
Egress cloudtypes.Firewall
}
// VPCsInput defines the VPC configuration.
type VPCsInput struct {
SubnetCIDR string
SubnetExtCIDR string
}
// CreateVPCs creates all necessary VPC networks.
func (c *Client) CreateVPCs(ctx context.Context, input VPCsInput) error {
c.network = c.name + "-" + c.uid
op, err := c.createVPC(ctx, c.network)
if err != nil {
return err
}
if err := c.waitForOperations(ctx, []Operation{op}); err != nil {
return err
}
if err := c.createSubnets(ctx, input.SubnetCIDR); err != nil {
return err
}
return nil
}
// createVPC creates a VPC network.
func (c *Client) createVPC(ctx context.Context, name string) (Operation, error) {
req := &computepb.InsertNetworkRequest{
NetworkResource: &computepb.Network{
AutoCreateSubnetworks: proto.Bool(false),
Description: proto.String("Constellation VPC"),
Name: proto.String(name),
},
Project: c.project,
}
return c.networksAPI.Insert(ctx, req)
}
// TerminateVPCs terminates all VPC networks.
//
// If the any network has firewall rules, these must be terminated first.
func (c *Client) TerminateVPCs(ctx context.Context) error {
if len(c.firewalls) != 0 {
return errors.New("client has firewalls, which must be deleted first")
}
if err := c.terminateSubnets(ctx); err != nil {
return err
}
var op Operation
var err error
if c.network != "" {
op, err = c.terminateVPC(ctx, c.network)
if err != nil {
return err
}
c.network = ""
}
return c.waitForOperations(ctx, []Operation{op})
}
// terminateVPC terminates a VPC network.
//
// If the network has firewall rules, these must be terminated first.
func (c *Client) terminateVPC(ctx context.Context, network string) (Operation, error) {
req := &computepb.DeleteNetworkRequest{
Project: c.project,
Network: network,
}
return c.networksAPI.Delete(ctx, req)
}
func (c *Client) createSubnets(ctx context.Context, subnetCIDR string) error {
c.subnetwork = "node-net-" + c.uid
c.secondarySubnetworkRange = "net-ext" + c.uid
op, err := c.createSubnet(ctx, c.subnetwork, subnetCIDR, c.network, c.secondarySubnetworkRange)
if err != nil {
return err
}
return c.waitForOperations(ctx, []Operation{op})
}
func (c *Client) createSubnet(ctx context.Context, name, cidr, network, secondaryRangeName string) (Operation, error) {
req := &computepb.InsertSubnetworkRequest{
Project: c.project,
Region: c.region,
SubnetworkResource: &computepb.Subnetwork{
IpCidrRange: proto.String(cidr),
Name: proto.String(name),
Network: proto.String("projects/" + c.project + "/global/networks/" + network),
SecondaryIpRanges: []*computepb.SubnetworkSecondaryRange{
{
RangeName: proto.String(secondaryRangeName),
IpCidrRange: proto.String("10.10.0.0/16"),
},
},
},
}
return c.subnetworksAPI.Insert(ctx, req)
}
func (c *Client) terminateSubnets(ctx context.Context) error {
var op Operation
var err error
if c.subnetwork != "" {
op, err = c.terminateSubnet(ctx, c.subnetwork)
if err != nil {
return err
}
}
return c.waitForOperations(ctx, []Operation{op})
}
func (c *Client) terminateSubnet(ctx context.Context, name string) (Operation, error) {
req := &computepb.DeleteSubnetworkRequest{
Project: c.project,
Region: c.region,
Subnetwork: name,
}
return c.subnetworksAPI.Delete(ctx, req)
}