github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/vault/vault_service_generator.go (about)

     1  package vault
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"log"
     7  	"regexp"
     8  	"sort"
     9  	"strings"
    10  
    11  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    12  	vault "github.com/hashicorp/vault/api"
    13  )
    14  
    15  type ServiceGenerator struct { //nolint
    16  	terraformutils.Service
    17  	client    *vault.Client
    18  	mountType string
    19  	resource  string
    20  }
    21  
    22  func (g *ServiceGenerator) setVaultClient() error {
    23  	client, err := vault.NewClient(&vault.Config{Address: g.Args["address"].(string)})
    24  	if err != nil {
    25  		return err
    26  	}
    27  	if g.Args["token"] != "" {
    28  		client.SetToken(g.Args["token"].(string))
    29  	}
    30  	g.client = client
    31  	return nil
    32  }
    33  
    34  func (g *ServiceGenerator) InitResources() error {
    35  	switch g.resource {
    36  	case "secret_backend":
    37  		return g.createSecretBackendResources()
    38  	case "secret_backend_role":
    39  		return g.createSecretBackendRoleResources()
    40  	case "auth_backend":
    41  		return g.createAuthBackendResources()
    42  	case "auth_backend_role":
    43  		return g.createAuthBackendEntityResources("role", "role")
    44  	case "auth_backend_user":
    45  		return g.createAuthBackendEntityResources("users", "user")
    46  	case "auth_backend_group":
    47  		return g.createAuthBackendEntityResources("groups", "group")
    48  	case "policy":
    49  		return g.createPolicyResources()
    50  	case "generic_secret":
    51  		return g.createGenericSecretResources()
    52  	case "mount":
    53  		return g.createMountResources()
    54  	default:
    55  		return errors.New("unsupported service type. shouldn't ever reach here")
    56  	}
    57  }
    58  
    59  func (g *ServiceGenerator) createSecretBackendResources() error {
    60  	mounts, err := g.mountsByType()
    61  	if err != nil {
    62  		return err
    63  	}
    64  	for _, mount := range mounts {
    65  		g.Resources = append(g.Resources,
    66  			terraformutils.NewSimpleResource(
    67  				mount,
    68  				mount,
    69  				fmt.Sprintf("vault_%s_secret_backend", g.mountType),
    70  				g.ProviderName,
    71  				[]string{}))
    72  	}
    73  	return nil
    74  }
    75  
    76  func (g *ServiceGenerator) createSecretBackendRoleResources() error {
    77  	mounts, err := g.mountsByType()
    78  	if err != nil {
    79  		return err
    80  	}
    81  	for _, mount := range mounts {
    82  		path := fmt.Sprintf("%s/roles", mount)
    83  		s, err := g.client.Logical().List(path)
    84  		if err != nil {
    85  			log.Printf("error calling path %s: %s", path, err)
    86  			continue
    87  		}
    88  		if s == nil {
    89  			log.Printf("call to %s returned nil result", path)
    90  			continue
    91  		}
    92  		roles, ok := s.Data["keys"]
    93  		if !ok {
    94  			log.Printf("no keys in call to %s", path)
    95  			continue
    96  		}
    97  		for _, role := range roles.([]interface{}) {
    98  			g.Resources = append(g.Resources,
    99  				terraformutils.NewSimpleResource(
   100  					fmt.Sprintf("%s/roles/%s", mount, role),
   101  					fmt.Sprintf("%s_%s", mount, role),
   102  					fmt.Sprintf("vault_%s_secret_backend_role", g.mountType),
   103  					g.ProviderName,
   104  					[]string{}))
   105  		}
   106  	}
   107  	return nil
   108  }
   109  
   110  func (g *ServiceGenerator) mountsByType() ([]string, error) {
   111  	mounts, err := g.client.Sys().ListMounts()
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	var typeMounts []string
   116  	for name, mount := range mounts {
   117  		if g.mountType == "" || mount.Type == g.mountType {
   118  			id := strings.ReplaceAll(name, "/", "")
   119  			typeMounts = append(typeMounts, id)
   120  		}
   121  	}
   122  	return typeMounts, nil
   123  }
   124  
   125  func (g *ServiceGenerator) createAuthBackendResources() error {
   126  	backends, err := g.backendsByType()
   127  	if err != nil {
   128  		return err
   129  	}
   130  	for _, backend := range backends {
   131  		g.Resources = append(g.Resources,
   132  			terraformutils.NewSimpleResource(
   133  				backend,
   134  				backend,
   135  				fmt.Sprintf("vault_%s_auth_backend", g.mountType),
   136  				g.ProviderName,
   137  				[]string{}))
   138  	}
   139  	return nil
   140  }
   141  
   142  func (g *ServiceGenerator) createAuthBackendEntityResources(apiEntity, tfEntity string) error {
   143  	backends, err := g.backendsByType()
   144  	if err != nil {
   145  		return err
   146  	}
   147  	for _, backend := range backends {
   148  		path := fmt.Sprintf("/auth/%s/%s", backend, apiEntity)
   149  		s, err := g.client.Logical().List(path)
   150  		if err != nil {
   151  			log.Printf("error calling path %s: %s", path, err)
   152  			continue
   153  		}
   154  		if s == nil {
   155  			log.Printf("call to %s returned nil result", path)
   156  			continue
   157  		}
   158  		names, ok := s.Data["keys"]
   159  		if !ok {
   160  			log.Printf("no keys in call to %s", path)
   161  			continue
   162  		}
   163  		for _, name := range names.([]interface{}) {
   164  			g.Resources = append(g.Resources,
   165  				terraformutils.NewSimpleResource(
   166  					fmt.Sprintf("auth/%s/%s/%s", backend, apiEntity, name),
   167  					fmt.Sprintf("%s_%s", backend, name),
   168  					fmt.Sprintf("vault_%s_auth_backend_%s", g.mountType, tfEntity),
   169  					g.ProviderName,
   170  					[]string{}))
   171  		}
   172  	}
   173  	return nil
   174  }
   175  
   176  func (g *ServiceGenerator) backendsByType() ([]string, error) {
   177  	authBackends, err := g.client.Sys().ListAuth()
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  	var typeBackends []string
   182  	for name, authBackend := range authBackends {
   183  		if authBackend.Type != g.mountType {
   184  			continue
   185  		}
   186  		id := strings.ReplaceAll(name, "/", "")
   187  		typeBackends = append(typeBackends, id)
   188  	}
   189  	return typeBackends, nil
   190  }
   191  
   192  func (g *ServiceGenerator) createPolicyResources() error {
   193  	policies, err := g.client.Sys().ListPolicies()
   194  	if err != nil {
   195  		return err
   196  	}
   197  	for _, policy := range policies {
   198  		if policy == "root" {
   199  			continue
   200  		}
   201  		g.Resources = append(g.Resources,
   202  			terraformutils.NewSimpleResource(
   203  				policy,
   204  				policy,
   205  				"vault_policy",
   206  				g.ProviderName,
   207  				[]string{}))
   208  	}
   209  	return nil
   210  }
   211  
   212  func (g *ServiceGenerator) createGenericSecretResources() error {
   213  	mounts, err := g.mountsByType()
   214  	if err != nil {
   215  		return err
   216  	}
   217  	for _, mount := range mounts {
   218  		path := fmt.Sprintf("%s/", mount)
   219  		s, err := g.client.Logical().List(path)
   220  		if err != nil {
   221  			log.Printf("error calling path %s: %s", path, err)
   222  			continue
   223  		}
   224  		if s == nil {
   225  			log.Printf("call to %s returned nil result", path)
   226  			continue
   227  		}
   228  		secrets, ok := s.Data["keys"]
   229  		if !ok {
   230  			log.Printf("no keys in call to %s", path)
   231  			continue
   232  		}
   233  		for _, secret := range secrets.([]interface{}) {
   234  			g.Resources = append(g.Resources,
   235  				terraformutils.NewSimpleResource(
   236  					fmt.Sprintf("%s/%s", mount, secret),
   237  					fmt.Sprintf("%s_%s", mount, secret),
   238  					"vault_generic_secret",
   239  					g.ProviderName,
   240  					[]string{}))
   241  		}
   242  	}
   243  	return nil
   244  }
   245  
   246  func (g *ServiceGenerator) createMountResources() error {
   247  	mounts, err := g.mountsByType()
   248  	if err != nil {
   249  		return err
   250  	}
   251  	for _, mount := range mounts {
   252  		g.Resources = append(g.Resources,
   253  			terraformutils.NewSimpleResource(
   254  				mount,
   255  				mount,
   256  				"vault_mount",
   257  				g.ProviderName,
   258  				[]string{}))
   259  	}
   260  	return nil
   261  }
   262  
   263  func (g *ServiceGenerator) PostConvertHook() error {
   264  	for _, resource := range g.Resources {
   265  		switch resource.InstanceInfo.Type {
   266  		case "vault_aws_secret_backend_role":
   267  			if policyDocument, ok := resource.Item["policy_document"]; ok {
   268  				// borrowed from providers/aws/aws_service.go
   269  				sanitizedPolicy := regexp.MustCompile(`(\${[0-9A-Za-z:]+})`).
   270  					ReplaceAllString(policyDocument.(string), "$$$1")
   271  				resource.Item["policy_document"] = fmt.Sprintf(`<<POLICY
   272  %s
   273  POLICY`, sanitizedPolicy)
   274  			}
   275  		case "vault_ldap_auth_backend_group":
   276  			if policies, ok := resource.Item["policies"]; ok {
   277  				var strPolicies []string
   278  				for _, policy := range policies.([]interface{}) {
   279  					strPolicies = append(strPolicies, policy.(string))
   280  				}
   281  				sort.Strings(strPolicies)
   282  				resource.Item["policies"] = strPolicies
   283  			}
   284  		}
   285  	}
   286  	return nil
   287  }