-
Notifications
You must be signed in to change notification settings - Fork 540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Nomad secret backend #923
Changes from 1 commit
d9e8686
98b38ee
8a817a1
2ac09f1
496d0d5
247f849
3d0c71e
9a611db
537b2d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package vault | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
"github.com/hashicorp/vault/api" | ||
) | ||
|
||
func nomadAccessCredentialsDataSource() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: readNomadCredsResource, | ||
Schema: map[string]*schema.Schema{ | ||
"backend": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
Description: "Nomad secret backend to generate tokens from.", | ||
}, | ||
"role": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
Description: "Name of the role.", | ||
}, | ||
"accessor_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
Description: "The public identifier for a specific token. It can be used to look up information about a token or to revoke a token.", | ||
}, | ||
"secret_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
Description: "Used to make requests to Nomad and should be kept private.", | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func readNomadCredsResource(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*api.Client) | ||
backend := d.Get("backend").(string) | ||
role := d.Get("role").(string) | ||
path := fmt.Sprintf("%s/creds/%s", backend, role) | ||
|
||
secret, err := client.Logical().Read(path) | ||
if err != nil { | ||
return fmt.Errorf("error reading from Vault: %s", err) | ||
} | ||
log.Printf("[DEBUG] Read %q from Vault", path) | ||
|
||
if secret == nil { | ||
return fmt.Errorf("no role found at %q", path) | ||
} | ||
|
||
accessorID := secret.Data["accessor_id"].(string) | ||
if accessorID == "" { | ||
return fmt.Errorf("accessor_id is not set in response") | ||
} | ||
|
||
secretID := secret.Data["secret_id"].(string) | ||
if secretID == "" { | ||
return fmt.Errorf("secret_id is not set in response") | ||
} | ||
|
||
d.SetId(accessorID) | ||
d.Set("accessor_id", accessorID) | ||
d.Set("secret_id", secretID) | ||
|
||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package vault | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/hashicorp/terraform-provider-vault/util" | ||
) | ||
|
||
func TestAccDataSourceNomadAccessCredentialsClientBasic(t *testing.T) { | ||
backend := acctest.RandomWithPrefix("tf-test-nomad") | ||
address, token := util.GetTestNomadCreds(t) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
Providers: testProviders, | ||
PreCheck: func() { util.TestAccPreCheck(t) }, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccDataSourceNomadAccessCredentialsConfig(backend, address, token, "test"), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttrSet("data.vault_nomad_access_token.token", "secret_id"), | ||
resource.TestCheckResourceAttrSet("data.vault_nomad_access_token.token", "accessor_id"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccDataSourceNomadAccessCredentialsManagementBasic(t *testing.T) { | ||
backend := acctest.RandomWithPrefix("tf-test-nomad") | ||
address, token := util.GetTestNomadCreds(t) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
Providers: testProviders, | ||
PreCheck: func() { util.TestAccPreCheck(t) }, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccDataSourceNomadAccessCredentialsManagementConfig(backend, address, token, "test"), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttrSet("data.vault_nomad_access_token.token", "secret_id"), | ||
resource.TestCheckResourceAttrSet("data.vault_nomad_access_token.token", "accessor_id"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccDataSourceNomadAccessCredentialsConfig(backend, address, token, role string) string { | ||
return fmt.Sprintf(` | ||
resource "vault_nomad_secret_backend" "config" { | ||
backend = "%s" | ||
description = "test description" | ||
default_lease_ttl_seconds = "3600" | ||
max_lease_ttl_seconds = "7200" | ||
address = "%s" | ||
token = "%s" | ||
} | ||
|
||
resource "vault_nomad_secret_role" "test" { | ||
backend = vault_nomad_secret_backend.config.backend | ||
role = "%s" | ||
policies = ["reaodnly"] | ||
} | ||
|
||
data "vault_nomad_access_token" "token" { | ||
backend = vault_nomad_secret_backend.config.backend | ||
role = vault_nomad_secret_role.test.role | ||
} | ||
`, backend, address, token, role) | ||
} | ||
|
||
func testAccDataSourceNomadAccessCredentialsManagementConfig(backend, address, token, role string) string { | ||
return fmt.Sprintf(` | ||
resource "vault_nomad_secret_backend" "config" { | ||
backend = "%s" | ||
description = "test description" | ||
default_lease_ttl_seconds = "3600" | ||
max_lease_ttl_seconds = "7200" | ||
address = "%s" | ||
token = "%s" | ||
} | ||
|
||
resource "vault_nomad_secret_role" "test" { | ||
backend = vault_nomad_secret_backend.config.backend | ||
role = "%s" | ||
type = "management" | ||
} | ||
|
||
data "vault_nomad_access_token" "token" { | ||
backend = vault_nomad_secret_backend.config.backend | ||
role = vault_nomad_secret_role.test.role | ||
} | ||
`, backend, address, token, role) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -231,6 +231,10 @@ var ( | |
Resource: adAccessCredentialsDataSource(), | ||
PathInventory: []string{"/ad/creds/{role}"}, | ||
}, | ||
"vault_nomad_access_token": { | ||
Resource: nomadAccessCredentialsDataSource(), | ||
PathInventory: []string{"/nomad/creds/{role}"}, | ||
}, | ||
"vault_aws_access_credentials": { | ||
Resource: awsAccessCredentialsDataSource(), | ||
PathInventory: []string{"/aws/creds"}, | ||
|
@@ -466,6 +470,18 @@ var ( | |
Resource: ldapAuthBackendGroupResource(), | ||
PathInventory: []string{"/auth/ldap/groups/{name}"}, | ||
}, | ||
"vault_nomad_secret_backend": { | ||
Resource: nomadSecretAccessBackendResource(), | ||
PathInventory: []string{"/nomad"}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @calvn Good question! Throughout the provider the mount and the config are the same resource. We derive the full path There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @calvn Having thought about combining There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is To Calvin's question this function does seem to cover the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can try in the morning having both but pointing to the same resource handler, maybe that won't cause issues. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update: both can't be present because the resource name is the key and you can't duplicate it. I changed the PathInventory to be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PathInventory is a list, so it could also be this: "vault_nomad_secret_backend": {
Resource: nomadSecretAccessBackendResource(),
PathInventory: []string{
"/nomad",
"/nomad/config/access",
}, But I think setting it to just "/nomad/config/access" makes sense 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh derp, yeah, that did work! Good call! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
}, | ||
"vault_nomad_secret_lease": { | ||
jasonodonnell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Resource: nomadSecretLeaseBackendResource(), | ||
PathInventory: []string{"/nomad/config/lease"}, | ||
}, | ||
"vault_nomad_secret_role": { | ||
Resource: nomadSecretBackendRoleResource(), | ||
PathInventory: []string{"/nomad/role/{role}"}, | ||
}, | ||
"vault_policy": { | ||
Resource: policyResource(), | ||
PathInventory: []string{"/sys/policy/{name}"}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use
path
here? Granted, we aren't using the ID at all that I can seeThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each call to this endpoint generates a new token, so we want the ID to be the unique identifier of that specific generated token. Path would be too generic I think?