Skip to content

Commit

Permalink
Issue GoogleCloudPlatform#962 add Hashicorp Vault provider partial su…
Browse files Browse the repository at this point in the history
…pport (GoogleCloudPlatform#964)

* Issue GoogleCloudPlatform#962 add Hashicorp Vault provider partial support

This commit includes the boilerplate for the Vault provider, as well
as support for Secret Engine, Secret Engine Roles, Auth Backends, Auth
Backend Roles, Auth Backend Users, Auth Backend Groups, and Policies. This is
done by instantiating a common Vault client using its official Go client
library and leveraging the naming convention of Vault tf resources to support
most of the Secret/Auth options available in the provider itself. The
provider configuration includes only the minimum required `address` and `token`
fields. Filtering roles/users/groups by mount type is supported as well as
basic filtering by resource ids.

* Issue GoogleCloudPlatform#962 linting fixes

* Issue GoogleCloudPlatform#962 add support for Vault generic secrets

* Issue GoogleCloudPlatform#962 fix filtering backends

* Issue GoogleCloudPlatform#962 post convert normalization of iam policies in vault aws secrets and fixing of policies without policy

* Issue GoogleCloudPlatform#962 linting fixes

* Issue GoogleCloudPlatform#962 add postconverthook for vault_ldap_auth_backend_group for deterministic order of policies
  • Loading branch information
ethpran authored Jun 23, 2021
1 parent c3a9e23 commit 50970d1
Show file tree
Hide file tree
Showing 8 changed files with 537 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ A CLI tool that generates `tf`/`json` and `tfstate` files based on existing infr
* [Xen Orchestra](/docs/xen.md)
* [GmailFilter](/docs/gmailfilter.md)
* [Grafana](/docs/grafana.md)
* [Vault](/docs/vault.md)
- [Contributing](#contributing)
- [Developing](#developing)
- [Infrastructure](#infrastructure)
Expand Down Expand Up @@ -277,6 +278,7 @@ Links to download Terraform Providers:
* Mikrotik provider >= 0.2.2 - [here](https://github.com/ddelnano/terraform-provider-mikrotik)
* Xen Orchestra provider >= 0.18.0 - [here](https://github.com/ddelnano/terraform-provider-xenorchestra)
* GmailFilter provider >= 1.0.1 - [here](https://github.com/yamamoto-febc/terraform-provider-gmailfilter)
* Vault provider - [here](https://github.com/hashicorp/terraform-provider-vault)

Information on provider plugins:
https://www.terraform.io/docs/configuration/providers.html
Expand Down
48 changes: 48 additions & 0 deletions cmd/provider_cmd_vault.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2019 The Terraformer Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cmd

import (
vault_terraforming "github.com/GoogleCloudPlatform/terraformer/providers/vault"

"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/spf13/cobra"
)

func newCmdVaultImporter(options ImportOptions) *cobra.Command {
var token, address string
cmd := &cobra.Command{
Use: "vault",
Short: "Import current state to Terraform configuration from Vault",
Long: "Import current state to Terraform configuration from Vault",
RunE: func(cmd *cobra.Command, args []string) error {
provider := newVaultProvider()
err := Import(provider, options, []string{address, token})
if err != nil {
return err
}
return nil
},
}

cmd.AddCommand(listCmd(newVaultProvider()))
cmd.PersistentFlags().StringVarP(&address, "address", "a", "", "env param VAULT_ADDR")
cmd.PersistentFlags().StringVarP(&token, "token", "t", "", "env param VAULT_TOKEN")
baseProviderFlags(cmd.PersistentFlags(), &options, "", "")
return cmd
}

func newVaultProvider() terraformutils.ProviderGenerator {
return &vault_terraforming.Provider{}
}
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func providerImporterSubcommands() []func(options ImportOptions) *cobra.Command
newCmdMikrotikImporter,
newCmdXenorchestraImporter,
newCmdGmailfilterImporter,
newCmdVaultImporter,
}
}

Expand Down Expand Up @@ -117,6 +118,7 @@ func providerGenerators() map[string]func() terraformutils.ProviderGenerator {
newMikrotikProvider,
newXenorchestraProvider,
newGmailfilterProvider,
newVaultProvider,
} {
list[providerGen().GetName()] = providerGen
}
Expand Down
87 changes: 87 additions & 0 deletions docs/vault.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
### Use with Vault

Example:

```
./terraformer import vault --resources=aws_secret_backend_role --token=YOUR_VAULT_TOKEN // or VAULT_TOKEN in env --address=YOUR_VAULT_ADDRESS // or VAULT_ADDR in env
./terraformer import vault --resources=policy --filter=policy=id1:id2:id4 --token=YOUR_VAULT_TOKEN // or VAULT_TOKEN in env --address=YOUR_VAULT_ADDRESS // or VAULT_ADDR in env
```

List of supported Datadog services:

* `ad_secret_backend`
* `ad_secret_backend`
* `ad_secret_backend_role`
* `ad_secret_backend_role`
* `alicloud_auth_backend_role`
* `alicloud_auth_backend_role`
* `approle_auth_backend_role`
* `approle_auth_backend_role`
* `aws_auth_backend_role`
* `aws_auth_backend_role`
* `aws_secret_backend`
* `aws_secret_backend`
* `aws_secret_backend_role`
* `aws_secret_backend_role`
* `azure_auth_backend_role`
* `azure_auth_backend_role`
* `azure_secret_backend`
* `azure_secret_backend`
* `azure_secret_backend_role`
* `azure_secret_backend_role`
* `cert_auth_backend_role`
* `cert_auth_backend_role`
* `consul_secret_backend`
* `consul_secret_backend`
* `consul_secret_backend_role`
* `consul_secret_backend_role`
* `database_secret_backend_role`
* `database_secret_backend_role`
* `gcp_auth_backend`
* `gcp_auth_backend`
* `gcp_auth_backend_role`
* `gcp_auth_backend_role`
* `gcp_secret_backend`
* `gcp_secret_backend`
* `generic_secret`
* `generic_secret`
* `github_auth_backend`
* `github_auth_backend`
* `jwt_auth_backend`
* `jwt_auth_backend`
* `jwt_auth_backend_role`
* `jwt_auth_backend_role`
* `kubernetes_auth_backend_role`
* `kubernetes_auth_backend_role`
* `ldap_auth_backend`
* `ldap_auth_backend`
* `ldap_auth_backend_group`
* `ldap_auth_backend_group`
* `ldap_auth_backend_user`
* `ldap_auth_backend_user`
* `nomad_secret_backend`
* `nomad_secret_backend`
* `okta_auth_backend`
* `okta_auth_backend`
* `okta_auth_backend_group`
* `okta_auth_backend_group`
* `okta_auth_backend_user`
* `okta_auth_backend_user`
* `pki_secret_backend`
* `pki_secret_backend`
* `pki_secret_backend_role`
* `pki_secret_backend_role`
* `policy`
* `policy`
* `rabbitmq_secret_backend`
* `rabbitmq_secret_backend`
* `rabbitmq_secret_backend_role`
* `rabbitmq_secret_backend_role`
* `ssh_secret_backend_role`
* `ssh_secret_backend_role`
* `terraform_cloud_secret_backend`
* `terraform_cloud_secret_backend`
* `token_auth_backend_role`
* `token_auth_backend_role`

[1]: https://github.com/GoogleCloudPlatform/terraformer/blob/master/README.md#filtering
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ require (
github.com/hashicorp/go-plugin v1.4.0
github.com/hashicorp/hcl v1.0.0
github.com/hashicorp/terraform v0.12.31
github.com/hashicorp/vault v0.10.4
github.com/heimweh/go-pagerduty v0.0.0-20210412205347-cc0e5d3c14d4
github.com/heroku/heroku-go/v5 v5.1.0
github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519 // indirect
Expand All @@ -126,6 +127,7 @@ require (
github.com/packethost/packngo v0.9.0
github.com/paultyng/go-newrelic/v4 v4.10.0
github.com/pkg/errors v0.9.1
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/spf13/cobra v1.1.1
github.com/spf13/pflag v1.0.5
github.com/tencentcloud/tencentcloud-sdk-go v3.0.233+incompatible
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
Expand Down Expand Up @@ -647,11 +648,13 @@ github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo=
github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-slug v0.4.1/go.mod h1:I5tq5Lv0E2xcNXNkmx7BSfzi1PsJ2cNjs3cC3LwyhK8=
github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-tfe v0.8.1/go.mod h1:XAV72S4O1iP8BDaqiaPLmL2B4EE6almocnOn8E8stHc=
Expand Down Expand Up @@ -688,6 +691,7 @@ github.com/hashicorp/terraform-plugin-sdk v1.6.0 h1:Um5hsAL7kKsfTHtan8lybY/d03F2
github.com/hashicorp/terraform-plugin-sdk v1.6.0/go.mod h1:H5QLx/uhwfxBZ59Bc5SqT19M4i+fYt7LZjHTpbLZiAg=
github.com/hashicorp/terraform-svchost v0.0.0-20191011084731-65d371908596 h1:hjyO2JsNZUKT1ym+FAdlBEkGPevazYsmVgIMw7dVELg=
github.com/hashicorp/terraform-svchost v0.0.0-20191011084731-65d371908596/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg=
github.com/hashicorp/vault v0.10.4 h1:4x0lHxui/ZRp/B3E0Auv1QNBJpzETqHR2kQD3mHSBJU=
github.com/hashicorp/vault v0.10.4/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
Expand Down Expand Up @@ -929,6 +933,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
Expand Down
100 changes: 100 additions & 0 deletions providers/vault/vault_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package vault

import (
"errors"
"fmt"
"os"

"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/zclconf/go-cty/cty"
)

type Provider struct {
terraformutils.Provider
token string
address string
}

func (p *Provider) Init(args []string) error {

if address := os.Getenv("VAULT_ADDR"); address != "" {
p.address = os.Getenv("VAULT_ADDR")
}

if token := os.Getenv("VAULT_TOKEN"); token != "" {
p.token = os.Getenv("VAULT_TOKEN")
}

if len(args) > 0 && args[0] != "" {
p.address = args[0]
}

if len(args) > 1 && args[1] != "" {
p.token = args[1]
}

return nil
}

func (p *Provider) GetConfig() cty.Value {
return cty.ObjectVal(map[string]cty.Value{
"token": cty.StringVal(p.token),
"address": cty.StringVal(p.address),
})
}

func (p *Provider) GetName() string {
return "vault"
}

func (p *Provider) InitService(serviceName string, verbose bool) error {
if service, ok := p.GetSupportedService()[serviceName]; ok {
p.Service = service
p.Service.SetName(serviceName)
p.Service.SetVerbose(verbose)
p.Service.SetProviderName(p.GetName())
p.Service.SetArgs(map[string]interface{}{
"token": p.token,
"address": p.address,
})
if err := service.(*ServiceGenerator).setVaultClient(); err != nil {
return err
}
return nil
}
return errors.New(p.GetName() + ": " + serviceName + " not supported service")
}

func getSupportedMountServices() map[string]terraformutils.ServiceGenerator {
services := make(map[string]terraformutils.ServiceGenerator)
mapping := map[string][]string{
"secret_backend": {"ad", "aws", "azure", "consul", "gcp", "nomad", "pki", "rabbitmq", "terraform_cloud"},
"secret_backend_role": {"ad", "aws", "azure", "consul", "database", "pki", "rabbitmq", "ssh"},
"auth_backend": {"gcp", "github", "jwt", "ldap", "okta"},
"auth_backend_role": {"alicloud", "approle", "aws", "azure", "cert", "gcp", "jwt", "kubernetes", "token"},
"auth_backend_user": {"ldap", "okta"},
"auth_backend_group": {"ldap", "okta"},
}
for resource, mountTypes := range mapping {
for _, mountType := range mountTypes {
services[fmt.Sprintf("%s_%s", mountType, resource)] =
&ServiceGenerator{mountType: mountType, resource: resource}
}
}
return services
}

func (p *Provider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
generators := getSupportedMountServices()
generators["policy"] = &ServiceGenerator{resource: "policy"}
generators["generic_secret"] = &ServiceGenerator{resource: "generic_secret", mountType: "kv"}
return generators
}

func (Provider) GetResourceConnections() map[string]map[string][]string {
return map[string]map[string][]string{}
}

func (Provider) GetProviderData(_ ...string) map[string]interface{} {
return map[string]interface{}{}
}
Loading

0 comments on commit 50970d1

Please sign in to comment.