credential/cert: support leasing and renewal

This commit is contained in:
Armon Dadgar
2015-04-24 12:58:39 -07:00
parent bfb0f08372
commit 8ae7b1288a
5 changed files with 52 additions and 3 deletions

View File

@@ -28,6 +28,8 @@ func Backend() *framework.Backend {
pathLogin(&b),
pathCerts(&b),
}),
AuthRenew: b.pathLoginRenew,
}
return b.Backend

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"testing"
"time"
"github.com/hashicorp/vault/logical"
logicaltest "github.com/hashicorp/vault/logical/testing"
@@ -62,7 +63,14 @@ func testAccStepLogin(t *testing.T, connState tls.ConnectionState) logicaltest.T
Path: "login",
Unauthenticated: true,
ConnState: &connState,
Check: logicaltest.TestCheckAuth([]string{"foo"}),
Check: func(resp *logical.Response) error {
if resp.Auth.Lease != 1000*time.Second {
t.Fatalf("bad lease length: %#v", resp.Auth)
}
fn := logicaltest.TestCheckAuth([]string{"foo"})
return fn(resp)
},
}
}
@@ -91,6 +99,7 @@ func testAccStepCert(
"certificate": string(cert),
"policies": policies,
"display_name": name,
"lease": 1000,
},
}
}

View File

@@ -2,6 +2,7 @@ package cert
import (
"strings"
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
@@ -30,6 +31,11 @@ func pathCerts(b *backend) *framework.Path {
Type: framework.TypeString,
Description: "Comma-seperated list of policies.",
},
"lease": &framework.FieldSchema{
Type: framework.TypeInt,
Description: "lease time in seconds. Defaults to 1 hour.",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
@@ -110,12 +116,20 @@ func (b *backend) pathCertWrite(
return logical.ErrorResponse("failed to parse certificate"), nil
}
// Parse the lease duration or default to 1h
leaseDur := time.Hour
leaseSec := d.Get("lease").(int)
if leaseSec > 0 {
leaseDur = time.Duration(leaseSec) * time.Second
}
// Store it
entry, err := logical.StorageEntryJSON("cert/"+name, &CertEntry{
Name: name,
Certificate: certificate,
DisplayName: displayName,
Policies: policies,
Lease: leaseDur,
})
if err != nil {
return nil, err
@@ -131,6 +145,7 @@ type CertEntry struct {
Certificate string
DisplayName string
Policies []string
Lease time.Duration
}
const pathCertHelpSyn = `

View File

@@ -60,6 +60,13 @@ func (b *backend) pathLogin(
Auth: &logical.Auth{
Policies: matched.Entry.Policies,
DisplayName: matched.Entry.DisplayName,
Metadata: map[string]string{
"cert_name": matched.Entry.Name,
},
LeaseOptions: logical.LeaseOptions{
Renewable: true,
Lease: matched.Entry.Lease,
},
},
}
return resp, nil
@@ -161,3 +168,18 @@ func validateConnState(roots *x509.CertPool, cs *tls.ConnectionState) ([][]*x509
}
return chains, nil
}
func (b *backend) pathLoginRenew(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
// Get the cert and validate auth
cert, err := b.Cert(req.Storage, req.Auth.Metadata["cert_name"])
if err != nil {
return nil, err
}
if cert == nil {
// User no longer exists, do not renew
return nil, nil
}
return framework.LeaseExtend(cert.Lease, 0)(req, d)
}

View File

@@ -30,11 +30,12 @@ trusted certificates that are allowed to authenticate. An example is shown below
Use `vault help` for more details.
```
$ vault write auth/cert/certs/web display_name=web policies=web,prod certificate=@web-cert.pem
$ vault write auth/cert/certs/web display_name=web policies=web,prod certificate=@web-cert.pem lease=3600
...
```
The above creates a new trusted certificate "web" with same display name
and the "web" and "prod" policies. The certificate (public key) used to verify
clients is given by the "web-cert.pem" file.
clients is given by the "web-cert.pem" file. Lastly, an optional lease value
can be provided in seconds to limit the lease period.