2015-03-04 21:10:10 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
2015-03-11 19:02:11 +00:00
|
|
|
"net/http/cookiejar"
|
2015-03-09 18:38:50 +00:00
|
|
|
"net/url"
|
2015-03-11 22:42:08 +00:00
|
|
|
"time"
|
|
|
|
|
2015-03-30 18:14:51 +00:00
|
|
|
vaultHttp "github.com/hashicorp/vault/http"
|
2015-03-04 21:10:10 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Config is used to configure the creation of the client.
|
|
|
|
type Config struct {
|
|
|
|
// Address is the address of the Vault server. This should be a complete
|
|
|
|
// URL such as "http://vault.example.com". If you need a custom SSL
|
|
|
|
// cert or want to enable insecure mode, you need to specify a custom
|
|
|
|
// HttpClient.
|
|
|
|
Address string
|
|
|
|
|
|
|
|
// HttpClient is the HTTP client to use. http.DefaultClient will be
|
2015-03-11 19:02:11 +00:00
|
|
|
// used if not specified. The HTTP client must have the cookie jar set
|
|
|
|
// to be able to store cookies, otherwise authentication (login) will
|
|
|
|
// not work properly. If the jar is nil, a default empty cookie jar
|
|
|
|
// will be set.
|
2015-03-04 21:10:10 +00:00
|
|
|
HttpClient *http.Client
|
|
|
|
}
|
|
|
|
|
|
|
|
// DefaultConfig returns a default configuration for the client. It is
|
|
|
|
// safe to modify the return value of this function.
|
2015-03-11 22:42:08 +00:00
|
|
|
func DefaultConfig() Config {
|
|
|
|
config := Config{
|
2015-03-04 21:10:10 +00:00
|
|
|
Address: "https://127.0.0.1:8200",
|
|
|
|
HttpClient: http.DefaultClient,
|
|
|
|
}
|
|
|
|
|
|
|
|
return config
|
|
|
|
}
|
|
|
|
|
|
|
|
// Client is the client to the Vault API. Create a client with
|
|
|
|
// NewClient.
|
|
|
|
type Client struct {
|
2015-03-09 18:38:50 +00:00
|
|
|
addr *url.URL
|
2015-03-04 21:10:10 +00:00
|
|
|
config Config
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewClient returns a new client for the given configuration.
|
|
|
|
func NewClient(c Config) (*Client, error) {
|
2015-03-09 18:38:50 +00:00
|
|
|
u, err := url.Parse(c.Address)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-03-11 19:02:11 +00:00
|
|
|
// Make a copy of the HTTP client so we can configure it without
|
|
|
|
// affecting the original
|
|
|
|
//
|
|
|
|
// If no cookie jar is set on the client, we set a default empty
|
|
|
|
// cookie jar.
|
2015-03-11 22:42:08 +00:00
|
|
|
if c.HttpClient.Jar == nil {
|
2015-03-11 19:02:11 +00:00
|
|
|
jar, err := cookiejar.New(&cookiejar.Options{})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-03-11 22:42:08 +00:00
|
|
|
c.HttpClient.Jar = jar
|
2015-03-11 19:02:11 +00:00
|
|
|
}
|
|
|
|
|
2015-03-04 21:10:10 +00:00
|
|
|
return &Client{
|
2015-03-09 18:38:50 +00:00
|
|
|
addr: u,
|
2015-03-04 21:10:10 +00:00
|
|
|
config: c,
|
|
|
|
}, nil
|
|
|
|
}
|
2015-03-09 18:38:50 +00:00
|
|
|
|
2015-03-11 22:42:08 +00:00
|
|
|
// Token returns the access token being used by this client. It will
|
|
|
|
// return the empty string if there is no token set.
|
|
|
|
func (c *Client) Token() string {
|
|
|
|
r := c.NewRequest("GET", "/")
|
|
|
|
for _, cookie := range c.config.HttpClient.Jar.Cookies(r.URL) {
|
2015-03-30 18:14:51 +00:00
|
|
|
if cookie.Name == vaultHttp.AuthCookieName {
|
2015-03-11 22:42:08 +00:00
|
|
|
return cookie.Value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2015-03-31 04:20:23 +00:00
|
|
|
// SetToken sets the token directly. This won't perform any auth
|
|
|
|
// verification, it simply sets the cookie properly for future requests.
|
|
|
|
func (c *Client) SetToken(v string) {
|
|
|
|
r := c.NewRequest("GET", "/")
|
|
|
|
c.config.HttpClient.Jar.SetCookies(r.URL, []*http.Cookie{
|
|
|
|
&http.Cookie{
|
|
|
|
Name: vaultHttp.AuthCookieName,
|
|
|
|
Value: v,
|
|
|
|
Path: "/",
|
|
|
|
Expires: time.Now().Add(365 * 24 * time.Hour),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-03-11 22:42:08 +00:00
|
|
|
// ClearToken deletes the token cookie if it is set or does nothing otherwise.
|
|
|
|
func (c *Client) ClearToken() {
|
|
|
|
r := c.NewRequest("GET", "/")
|
|
|
|
c.config.HttpClient.Jar.SetCookies(r.URL, []*http.Cookie{
|
|
|
|
&http.Cookie{
|
2015-03-30 18:14:51 +00:00
|
|
|
Name: vaultHttp.AuthCookieName,
|
2015-03-11 22:42:08 +00:00
|
|
|
Value: "",
|
|
|
|
Expires: time.Now().Add(-1 * time.Hour),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-03-09 18:38:50 +00:00
|
|
|
// NewRequest creates a new raw request object to query the Vault server
|
|
|
|
// configured for this client. This is an advanced method and generally
|
|
|
|
// doesn't need to be called externally.
|
|
|
|
func (c *Client) NewRequest(method, path string) *Request {
|
|
|
|
return &Request{
|
|
|
|
Method: method,
|
|
|
|
URL: &url.URL{
|
|
|
|
Scheme: c.addr.Scheme,
|
|
|
|
Host: c.addr.Host,
|
|
|
|
Path: path,
|
|
|
|
},
|
|
|
|
Params: make(map[string][]string),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// RawRequest performs the raw request given. This request may be against
|
|
|
|
// a Vault server not configured with this client. This is an advanced operation
|
|
|
|
// that generally won't need to be called externally.
|
2015-03-11 18:33:20 +00:00
|
|
|
func (c *Client) RawRequest(r *Request) (*Response, error) {
|
2015-03-09 18:38:50 +00:00
|
|
|
req, err := r.ToHTTP()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-04-07 18:15:20 +00:00
|
|
|
var result *Response
|
2015-03-09 18:38:50 +00:00
|
|
|
resp, err := c.config.HttpClient.Do(req)
|
2015-04-07 18:15:20 +00:00
|
|
|
if resp != nil {
|
|
|
|
result = &Response{Response: resp}
|
|
|
|
}
|
2015-03-09 18:38:50 +00:00
|
|
|
if err != nil {
|
2015-04-07 18:15:20 +00:00
|
|
|
return result, err
|
2015-03-09 18:38:50 +00:00
|
|
|
}
|
|
|
|
|
2015-03-11 18:46:07 +00:00
|
|
|
if err := result.Error(); err != nil {
|
2015-04-07 18:15:20 +00:00
|
|
|
return result, err
|
2015-03-11 18:46:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
2015-03-09 18:38:50 +00:00
|
|
|
}
|