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 }