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  }