Skip to content

Commit

Permalink
vault_token: add pgp_key support (hashicorp#686)
Browse files Browse the repository at this point in the history
* vault_token: add pgp_key support

Signed-off-by: Yoan Blanc <[email protected]>

* update vendor

Signed-off-by: Yoan Blanc <[email protected]>

* fixup! vault_token: add pgp_key support

Signed-off-by: Yoan Blanc <[email protected]>

* vault_token: conflicts with renewable doesn't work

The default value being true, it should simply ignore it when gpg is used.

Signed-off-by: Yoan Blanc <[email protected]>

* token: test and docs

Signed-off-by: Yoan Blanc <[email protected]>
  • Loading branch information
greut authored Mar 30, 2020
1 parent 2867166 commit 298c0ee
Show file tree
Hide file tree
Showing 66 changed files with 18,069 additions and 2 deletions.
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVY
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
github.com/keybase/go-crypto v0.0.0-20190403132359-d65b6b94177f h1:Gsc9mVHLRqBjMgdQCghN9NObCcRncDqxJvBvEaIIQEo=
github.com/keybase/go-crypto v0.0.0-20190403132359-d65b6b94177f/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
Expand Down
42 changes: 41 additions & 1 deletion vault/resource_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/encryption"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/vault/api"
)
Expand Down Expand Up @@ -143,6 +144,18 @@ func tokenResource() *schema.Resource {
Description: "The client wrapping accessor.",
Sensitive: true,
},
"pgp_key": {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
Description: "The PGP key (base64 encoded) to encrypt the token.",
},
"encrypted_client_token": {
Type: schema.TypeString,
Computed: true,
Description: "The client token encrypted using the provided PGP key.",
Sensitive: true,
},
},
}
}
Expand Down Expand Up @@ -253,7 +266,23 @@ func tokenCreate(d *schema.ResourceData, meta interface{}) error {
d.Set("wrapped_token", resp.WrapInfo.Token)
d.Set("wrapping_accessor", resp.WrapInfo.Accessor)
} else {
d.Set("client_token", resp.Auth.ClientToken)
if v, ok := d.GetOk("pgp_key"); ok {
pgpKey := v.(string)
encryptionKey, err := encryption.RetrieveGPGKey(pgpKey)
if err != nil {
return err
}
_, encrypted, err := encryption.EncryptValue(encryptionKey, resp.Auth.ClientToken, "Vault Token")
if err != nil {
return err
}
d.Set("client_token", "")
d.Set("encrypted_client_token", encrypted)
} else {
d.Set("pgp_key", "")
d.Set("client_token", resp.Auth.ClientToken)
d.Set("encrypted_client_token", "")
}
}

d.SetId(accessor)
Expand Down Expand Up @@ -292,6 +321,12 @@ func tokenRead(d *schema.ResourceData, meta interface{}) error {
d.Set("renewable", resp.Data["renewable"])
d.Set("display_name", strings.TrimPrefix(resp.Data["display_name"].(string), "token-"))
d.Set("num_uses", resp.Data["num_uses"])
if _, ok := d.GetOk("pgp_key"); !ok {
d.Set("pgp_key", "")
}
if _, ok := d.GetOk("encrypted_client_token"); !ok {
d.Set("encrypted_client_token", "")
}

issueTime, err := time.Parse(time.RFC3339Nano, resp.Data["issue_time"].(string))
if err != nil {
Expand All @@ -306,6 +341,11 @@ func tokenRead(d *schema.ResourceData, meta interface{}) error {
d.Set("lease_duration", int(expireTime.Sub(issueTime).Seconds()))

if d.Get("renewable").(bool) && tokenCheckLease(d) {
if id == "" {
log.Printf("[DEBUG] Lease for token access %q cannot be renewed as it's been encrypted.", accessor)
return nil
}

log.Printf("[DEBUG] Lease for token accessor %q expiring soon, renewing", accessor)

increment := d.Get("lease_duration").(int)
Expand Down
46 changes: 45 additions & 1 deletion vault/resource_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func TestResourceToken_basic(t *testing.T) {
resource.TestCheckResourceAttrSet("vault_token.test", "lease_duration"),
resource.TestCheckResourceAttrSet("vault_token.test", "lease_started"),
resource.TestCheckResourceAttrSet("vault_token.test", "client_token"),
resource.TestCheckResourceAttr("vault_token.test", "encrypted_client_token", ""),
),
},
},
Expand All @@ -59,14 +60,15 @@ func TestResourceToken_import(t *testing.T) {
resource.TestCheckResourceAttrSet("vault_token.test", "lease_duration"),
resource.TestCheckResourceAttrSet("vault_token.test", "lease_started"),
resource.TestCheckResourceAttrSet("vault_token.test", "client_token"),
resource.TestCheckResourceAttr("vault_token.test", "encrypted_client_token", ""),
),
},
{
ResourceName: "vault_token.test",
ImportState: true,
ImportStateVerify: true,
// the API can't serve these fields, so ignore them
ImportStateVerifyIgnore: []string{"ttl", "lease_duration", "lease_started", "client_token"},
ImportStateVerifyIgnore: []string{"ttl", "lease_duration", "lease_started", "client_token", "encrypted_client_token"},
},
},
})
Expand Down Expand Up @@ -108,6 +110,7 @@ func TestResourceToken_full(t *testing.T) {
resource.TestCheckResourceAttr("vault_token.test", "lease_duration", "59"),
resource.TestCheckResourceAttrSet("vault_token.test", "lease_started"),
resource.TestCheckResourceAttrSet("vault_token.test", "client_token"),
resource.TestCheckResourceAttr("vault_token.test", "encrypted_client_token", ""),
),
},
},
Expand Down Expand Up @@ -206,6 +209,7 @@ func TestResourceToken_expire(t *testing.T) {
resource.TestCheckResourceAttr("vault_token.test", "lease_duration", "9"),
resource.TestCheckResourceAttrSet("vault_token.test", "lease_started"),
resource.TestCheckResourceAttrSet("vault_token.test", "client_token"),
resource.TestCheckResourceAttr("vault_token.test", "encrypted_client_token", ""),
),
},
},
Expand Down Expand Up @@ -243,6 +247,7 @@ func TestResourceToken_renew(t *testing.T) {
resource.TestCheckResourceAttr("vault_token.test", "lease_duration", "29"),
resource.TestCheckResourceAttrSet("vault_token.test", "lease_started"),
resource.TestCheckResourceAttrSet("vault_token.test", "client_token"),
resource.TestCheckResourceAttr("vault_token.test", "encrypted_client_token", ""),
),
},
{
Expand All @@ -256,6 +261,7 @@ func TestResourceToken_renew(t *testing.T) {
resource.TestCheckResourceAttrSet("vault_token.test", "lease_duration"),
resource.TestCheckResourceAttrSet("vault_token.test", "lease_started"),
resource.TestCheckResourceAttrSet("vault_token.test", "client_token"),
resource.TestCheckResourceAttr("vault_token.test", "encrypted_client_token", ""),
),
},
{
Expand All @@ -272,6 +278,7 @@ func TestResourceToken_renew(t *testing.T) {
resource.TestCheckResourceAttr("vault_token.test", "lease_duration", "29"),
resource.TestCheckResourceAttrSet("vault_token.test", "lease_started"),
resource.TestCheckResourceAttrSet("vault_token.test", "client_token"),
resource.TestCheckResourceAttr("vault_token.test", "encrypted_client_token", ""),
),
},
},
Expand Down Expand Up @@ -424,3 +431,40 @@ func testResourceTokenWaitRenewMinLeaseTime(n string) resource.TestCheckFunc {
return nil
}
}

func TestResourceToken_pgp(t *testing.T) {
resource.Test(t, resource.TestCase{
Providers: testProviders,
PreCheck: func() { testAccPreCheck(t) },
CheckDestroy: testResourceTokenCheckDestroy,
Steps: []resource.TestStep{
{
Config: testResourceTokenConfig_pgp(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("vault_token.test", "policies.#", "1"),
resource.TestCheckResourceAttr("vault_token.test", "ttl", "60s"),
resource.TestCheckResourceAttrSet("vault_token.test", "lease_duration"),
resource.TestCheckResourceAttrSet("vault_token.test", "lease_started"),
resource.TestCheckResourceAttr("vault_token.test", "client_token", ""),
resource.TestCheckResourceAttrSet("vault_token.test", "encrypted_client_token"),
),
},
},
})
}

func testResourceTokenConfig_pgp() string {
return `
resource "vault_policy" "test" {
name = "test"
policy = <<EOT
path "secret/*" { capabilities = [ "list" ] }
EOT
}
resource "vault_token" "test" {
ttl = "60s"
policies = [ "${vault_policy.test.name}" ]
pgp_key = "keybase:terraformacctest"
}`
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 298c0ee

Please sign in to comment.