-
Notifications
You must be signed in to change notification settings - Fork 540
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #198 from petems/add_gcp_auth_backend_resource
Adding GCP Auth backend resource
- Loading branch information
Showing
4 changed files
with
323 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
package vault | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"log" | ||
"strings" | ||
|
||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/hashicorp/vault/api" | ||
) | ||
|
||
const gcpAuthType string = "gcp" | ||
|
||
func gcpAuthBackendResource() *schema.Resource { | ||
return &schema.Resource{ | ||
|
||
Create: gcpAuthBackendWrite, | ||
Update: gcpAuthBackendUpdate, | ||
Read: gcpAuthBackendRead, | ||
Delete: gcpAuthBackendDelete, | ||
Exists: gcpAuthBackendExists, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"credentials": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
StateFunc: NormalizeCredentials, | ||
ValidateFunc: ValidateCredentials, | ||
Sensitive: true, | ||
}, | ||
"description": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
"client_id": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
"private_key_id": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
"project_id": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
"client_email": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
"path": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ForceNew: true, | ||
Default: "gcp", | ||
StateFunc: func(v interface{}) string { | ||
return strings.Trim(v.(string), "/") | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func ValidateCredentials(configI interface{}, k string) ([]string, []error) { | ||
credentials := configI.(string) | ||
dataMap := map[string]interface{}{} | ||
err := json.Unmarshal([]byte(credentials), &dataMap) | ||
if err != nil { | ||
return nil, []error{err} | ||
} | ||
return nil, nil | ||
} | ||
|
||
func NormalizeCredentials(configI interface{}) string { | ||
credentials := configI.(string) | ||
|
||
dataMap := map[string]interface{}{} | ||
err := json.Unmarshal([]byte(credentials), &dataMap) | ||
if err != nil { | ||
// The validate function should've taken care of this. | ||
log.Printf("[ERROR] Invalid JSON data in vault_gcp_auth_backend: %s", err) | ||
return "" | ||
} | ||
|
||
ret, err := json.Marshal(dataMap) | ||
if err != nil { | ||
// Should never happen. | ||
log.Printf("[ERROR] Problem normalizing JSON for vault_gcp_auth_backend: %s", err) | ||
return credentials | ||
} | ||
|
||
return string(ret) | ||
} | ||
|
||
func gcpAuthBackendConfigPath(path string) string { | ||
return "auth/" + strings.Trim(path, "/") + "/config" | ||
} | ||
|
||
func gcpAuthBackendWrite(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*api.Client) | ||
|
||
authType := gcpAuthType | ||
path := d.Get("path").(string) | ||
desc := d.Get("description").(string) | ||
|
||
log.Printf("[DEBUG] Enabling gcp auth backend %q", path) | ||
err := client.Sys().EnableAuth(path, authType, desc) | ||
if err != nil { | ||
return fmt.Errorf("error enabling gcp auth backend %q: %s", path, err) | ||
} | ||
log.Printf("[DEBUG] Enabled gcp auth backend %q", path) | ||
|
||
d.SetId(path) | ||
|
||
return gcpAuthBackendUpdate(d, meta) | ||
} | ||
|
||
func gcpAuthBackendUpdate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*api.Client) | ||
|
||
path := gcpAuthBackendConfigPath(d.Id()) | ||
data := map[string]interface{}{} | ||
|
||
if v, ok := d.GetOk("credentials"); ok { | ||
data["credentials"] = v.(string) | ||
} | ||
|
||
log.Printf("[DEBUG] Writing gcp config %q", path) | ||
_, err := client.Logical().Write(path, data) | ||
|
||
if err != nil { | ||
d.SetId("") | ||
return fmt.Errorf("error writing gcp config %q: %s", path, err) | ||
} | ||
log.Printf("[DEBUG] Wrote gcp config %q", path) | ||
|
||
return gcpAuthBackendRead(d, meta) | ||
} | ||
|
||
func gcpAuthBackendRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*api.Client) | ||
path := gcpAuthBackendConfigPath(d.Id()) | ||
|
||
log.Printf("[DEBUG] Reading gcp auth backend config %q", path) | ||
resp, err := client.Logical().Read(path) | ||
if err != nil { | ||
return fmt.Errorf("error reading gcp auth backend config %q: %s", path, err) | ||
} | ||
log.Printf("[DEBUG] Read gcp auth backend config %q", path) | ||
|
||
if resp == nil { | ||
log.Printf("[WARN] gcp auth backend config %q not found, removing from state", path) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
d.Set("private_key_id", resp.Data["private_key_id"]) | ||
d.Set("client_id", resp.Data["client_id"]) | ||
d.Set("project_id", resp.Data["project_id"]) | ||
d.Set("client_email", resp.Data["client_email"]) | ||
|
||
return nil | ||
} | ||
|
||
func gcpAuthBackendDelete(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*api.Client) | ||
path := d.Id() | ||
|
||
log.Printf("[DEBUG] Deleting gcp auth backend %q", path) | ||
err := client.Sys().DisableAuth(path) | ||
if err != nil { | ||
return fmt.Errorf("error deleting gcp auth backend %q: %q", path, err) | ||
} | ||
log.Printf("[DEBUG] Deleted gcp auth backend %q", path) | ||
|
||
return nil | ||
} | ||
|
||
func gcpAuthBackendExists(d *schema.ResourceData, meta interface{}) (bool, error) { | ||
client := meta.(*api.Client) | ||
path := gcpAuthBackendConfigPath(d.Id()) | ||
|
||
log.Printf("[DEBUG] Checking if gcp auth backend %q exists", path) | ||
resp, err := client.Logical().Read(path) | ||
if err != nil { | ||
return true, fmt.Errorf("error checking for existence of gcp config %q: %s", path, err) | ||
} | ||
log.Printf("[DEBUG] Checked if gcp auth backend %q exists", path) | ||
|
||
return resp != nil, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package vault | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
"github.com/hashicorp/vault/api" | ||
) | ||
|
||
const gcpJSONCredentials string = ` | ||
{ | ||
"type": "service_account", | ||
"project_id": "terraform-vault-provider-a13efc8a", | ||
"private_key_id": "b1e1f3cdd7fc134afsdg3547828dc2bb9dff8480", | ||
"private_key": "-----BEGIN PRIVATE KEY-----\nABC123\n-----END PRIVATE KEY-----\n", | ||
"client_email": "terraform-vault-user@terraform-vault-provider-adf134rfds.iam.gserviceaccount.com", | ||
"client_id": "123134135242342423", | ||
"auth_uri": "https://accounts.google.com/o/oauth2/auth", | ||
"token_uri": "https://oauth2.googleapis.com/token", | ||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", | ||
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/vault-auth-checker%40terraform-vault-provider-adf134rfds.iam.gserviceaccount.com" | ||
} | ||
` | ||
|
||
func TestGCPAuthBackend_basic(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testProviders, | ||
CheckDestroy: testGCPAuthBackendDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testGCPAuthBackendConfig_basic(gcpJSONCredentials), | ||
Check: testGCPAuthBackendCheck_attrs(), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testGCPAuthBackendDestroy(s *terraform.State) error { | ||
client := testProvider.Meta().(*api.Client) | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "vault_gcp_auth_backend" { | ||
continue | ||
} | ||
secret, err := client.Logical().Read(rs.Primary.ID) | ||
if err != nil { | ||
return fmt.Errorf("error checking for gcp auth backend %q: %s", rs.Primary.ID, err) | ||
} | ||
if secret != nil { | ||
return fmt.Errorf("gcp auth backend %q still exists", rs.Primary.ID) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func testGCPAuthBackendCheck_attrs() resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
resourceState := s.Modules[0].Resources["vault_gcp_auth_backend.test"] | ||
if resourceState == nil { | ||
return fmt.Errorf("resource not found in state") | ||
} | ||
|
||
instanceState := resourceState.Primary | ||
if instanceState == nil { | ||
return fmt.Errorf("resource has no primary instance") | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testGCPAuthBackendConfig_basic(credentials string) string { | ||
return fmt.Sprintf(` | ||
variable "json_credentials" { | ||
type = "string" | ||
default = %q | ||
} | ||
resource "vault_gcp_auth_backend" "test" { | ||
credentials = "${var.json_credentials}" | ||
} | ||
`, credentials) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
--- | ||
layout: "vault" | ||
page_title: "Vault: vault_auth_backend resource" | ||
sidebar_current: "docs-vault-resource-gcp-auth-backend-role" | ||
description: |- | ||
Managing roles in an GCP auth backend in Vault | ||
--- | ||
|
||
# vault\_gcp\_auth\_backend\ | ||
|
||
Provides a resource to configure the [GCP auth backend within Vault](https://www.vaultproject.io/docs/auth/gcp.html). | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "vault_gcp_auth_backend" "gcp" { | ||
credentials = "${file("vault-gcp-credentials.json")}" | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `credentials` - (Required) A JSON string containing the contents of a GCP credentials file. | ||
|
||
For more details on the usage of each argument consult the [Vault GCP API documentation](https://www.vaultproject.io/api/auth/gcp/index.html#configure). | ||
|
||
## Attribute Reference | ||
|
||
In addition to the fields above, the following attributes are also exposed: | ||
|
||
* `client_id` - The Client ID of the credentials | ||
|
||
* `private_key_id` - The ID of the private key from the credentials | ||
|
||
* `project_id` - The GCP Project ID | ||
|
||
* `client_email` - The clients email assosiated with the credentials |