Listen for events and forward to external security scanning services.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

openstack.go 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package main
  2. /*
  3. openstack - This file includes all of the logic necessary to interact with
  4. OpenStack. This is extrapolated out so that an OpenStackActioner
  5. interface can be passed to functions. Doing this allows testing by mock
  6. classes to be created that can be passed to functions.
  7. Since this is a wrapper around the gophercloud libraries, this does not need
  8. testing.
  9. */
  10. import (
  11. "fmt"
  12. "log"
  13. "github.com/rackspace/gophercloud"
  14. "github.com/rackspace/gophercloud/openstack"
  15. "github.com/rackspace/gophercloud/openstack/networking/v2/ports"
  16. "github.com/rackspace/gophercloud/pagination"
  17. )
  18. // OpenStackActioner is an interface for an OpenStackActions class.
  19. // Having this as an interface allows us to pass in a dummy class for testing
  20. // that just returns mocked data.
  21. type OpenStackActioner interface {
  22. GetPortList() []OpenStackIPMap
  23. Connect(string, string) error
  24. }
  25. // OpenStackActions is a class that handles all interactions directly with
  26. // OpenStack. See the comment on OpenStackActioner for rationale.
  27. type OpenStackActions struct {
  28. gopherCloudClient *gophercloud.ProviderClient
  29. neutronClient *gophercloud.ServiceClient
  30. Options OpenStackOptions
  31. }
  32. // OpenStackOptions is a class to convey all of the configurable options for the
  33. // OpenStackActions class.
  34. type OpenStackOptions struct {
  35. KeystoneURI string
  36. Password string
  37. RegionName string
  38. TenantID string
  39. UserName string
  40. }
  41. // OpenStackIPMap is a struct that is used to capture the mapping of IP address
  42. // to security group. It is what is returned, in array form, from port list.
  43. type OpenStackIPMap struct {
  44. ipAddress string
  45. securityGroup string
  46. }
  47. // GetPortList is a method that uses GopherCloud to query OpenStack for a
  48. // list of ports, with their associated security group. It returns an array of
  49. // OpenStackIPMap.
  50. func (s OpenStackActions) GetPortList() []OpenStackIPMap {
  51. // Make port list request to neutron
  52. var ips []OpenStackIPMap
  53. portListOpts := ports.ListOpts{
  54. TenantID: s.Options.TenantID,
  55. }
  56. if s.neutronClient == nil {
  57. log.Println("Error: neutronClient is nil")
  58. }
  59. pager := ports.List(s.neutronClient, portListOpts)
  60. // Define an anonymous function to be executed on each page's iteration
  61. pager.EachPage(func(page pagination.Page) (bool, error) {
  62. portList, err := ports.ExtractPorts(page)
  63. if err != nil {
  64. // ignore ?
  65. }
  66. for _, p := range portList {
  67. // "p" will be a ports.Port
  68. for _, fixedIP := range p.FixedIPs {
  69. for _, securityGroup := range p.SecurityGroups {
  70. ips = append(ips, OpenStackIPMap{
  71. ipAddress: fixedIP.IPAddress,
  72. securityGroup: securityGroup,
  73. })
  74. }
  75. }
  76. }
  77. return true, err
  78. })
  79. return ips
  80. }
  81. // Connect is the method that establishes a connection to the OpenStack
  82. // service.
  83. func (s *OpenStackActions) Connect(tenantID string, username string) error {
  84. var err error
  85. keystoneOpts := gophercloud.AuthOptions{
  86. IdentityEndpoint: s.Options.KeystoneURI,
  87. TenantID: tenantID,
  88. Username: username,
  89. Password: s.Options.Password,
  90. AllowReauth: true,
  91. }
  92. log.Println(fmt.Sprintf("Connecting to keystone %q in region %q for tenant %q with user %q", s.Options.KeystoneURI,
  93. s.Options.RegionName, tenantID, username))
  94. s.gopherCloudClient, err = openstack.AuthenticatedClient(keystoneOpts)
  95. if err != nil {
  96. return fmt.Errorf("unable to connect to %s using user %s for tenant %s: %s",
  97. s.Options.KeystoneURI, s.Options.UserName, s.Options.TenantID, err)
  98. }
  99. log.Println("Connected to gophercloud ", s.Options.KeystoneURI)
  100. neutronOpts := gophercloud.EndpointOpts{
  101. Name: "neutron",
  102. Region: s.Options.RegionName,
  103. }
  104. s.neutronClient, err = openstack.NewNetworkV2(s.gopherCloudClient, neutronOpts)
  105. if err != nil {
  106. return fmt.Errorf("unable to connect to neutron using user %s in region %s: %s",
  107. s.Options.UserName, s.Options.RegionName, err)
  108. }
  109. return nil
  110. }