Merge branch 'master' into jo-upgrade-copy
This commit is contained in:
commit
80262092af
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -8,21 +8,27 @@ DEPRECATIONS/CHANGES:
|
||||||
|
|
||||||
FEATURES:
|
FEATURES:
|
||||||
|
|
||||||
|
* Azure Key Vault Auto Unseal/Seal Wrap Support (Enterprise): Azure Key Vault
|
||||||
|
can now be used a support seal for Auto Unseal and Seal Wrapping.
|
||||||
* Cert auth CIDR restrictions: When using the `cert` auth method you can now
|
* Cert auth CIDR restrictions: When using the `cert` auth method you can now
|
||||||
limit authentication to specific CIDRs; these will also be encoded in
|
limit authentication to specific CIDRs; these will also be encoded in
|
||||||
resultant tokens to limit their use.
|
resultant tokens to limit their use.
|
||||||
|
* Userpass auth CIDR restrictions: When using the `userpass` auth method you
|
||||||
|
can now limit authentication to specific CIDRs; these will also be encoded
|
||||||
|
in resultant tokens to limit their use.
|
||||||
|
|
||||||
IMPROVEMENTS:
|
IMPROVEMENTS:
|
||||||
|
|
||||||
* api: Close renewer's doneCh when the renewer is stopped, so that programs
|
* api: Close renewer's doneCh when the renewer is stopped, so that programs
|
||||||
expecting a final value through doneCh behave correctly [GH-4472]
|
expecting a final value through doneCh behave correctly [GH-4472]
|
||||||
|
* auth/cert: Break out `allowed_names` into component parts and add
|
||||||
|
`allowed_uri_sans` [GH-4231]
|
||||||
* cli: `vault login` now supports a `-no-print` flag to suppress printing
|
* cli: `vault login` now supports a `-no-print` flag to suppress printing
|
||||||
token information but still allow storing into the token helper [GH-4454]
|
token information but still allow storing into the token helper [GH-4454]
|
||||||
* core/pkcs11 (enterprise): Add support for CKM_AES_CBS_PAD, CKM_RSA_PKCS, and
|
* core/pkcs11 (enterprise): Add support for CKM_AES_CBC_PAD, CKM_RSA_PKCS, and
|
||||||
CKM_RSA_PKCS_OAEP mechanisms
|
CKM_RSA_PKCS_OAEP mechanisms
|
||||||
* core/pkcs11 (enterprise): HSM slots can now be selected by token label instead
|
* core/pkcs11 (enterprise): HSM slots can now be selected by token label instead
|
||||||
of just slot number
|
of just slot number
|
||||||
* core/seal (enterprise): Lazily rewrap data when seal keys are rotated
|
|
||||||
* expiration: Allow revoke-prefix and revoke-force to work on single leases as
|
* expiration: Allow revoke-prefix and revoke-force to work on single leases as
|
||||||
well as prefixes [GH-4450]
|
well as prefixes [GH-4450]
|
||||||
|
|
||||||
|
@ -39,12 +45,19 @@ BUG FIXES:
|
||||||
parameters were used [GH-4582]
|
parameters were used [GH-4582]
|
||||||
* secret/gcp: Make `bound_region` able to use short names
|
* secret/gcp: Make `bound_region` able to use short names
|
||||||
* secret/kv: Fix response wrapping for KV v2 [GH-4511]
|
* secret/kv: Fix response wrapping for KV v2 [GH-4511]
|
||||||
|
* secret/kv: Fix address flag not being honored correctly [GH-4617]
|
||||||
* secret/pki: Fix `key_type` not being allowed to be set to `any` [GH-4595]
|
* secret/pki: Fix `key_type` not being allowed to be set to `any` [GH-4595]
|
||||||
* secret/pki: Fix path length parameter being ignored when using
|
* secret/pki: Fix path length parameter being ignored when using
|
||||||
`use_csr_values` and signing an intermediate CA cert [GH-4459]
|
`use_csr_values` and signing an intermediate CA cert [GH-4459]
|
||||||
* storage/dynamodb: Fix listing when one child is left within a nested path
|
* storage/dynamodb: Fix listing when one child is left within a nested path
|
||||||
[GH-4570]
|
[GH-4570]
|
||||||
* ui: Fix HMAC algorithm in transit [GH-4604]
|
* ui: Fix HMAC algorithm in transit [GH-4604]
|
||||||
|
* ui: Fix unwrap of auth responses via the UI's unwrap tool [GH-4611]
|
||||||
|
* replication: Fix error while running plugins on a newly created replication
|
||||||
|
secondary
|
||||||
|
* replication: Fix issue with token store lookups after a secondary's mount table
|
||||||
|
is invalidated.
|
||||||
|
* replication: Improve startup time when a large merkle index is in use.
|
||||||
|
|
||||||
## 0.10.1/0.9.7 (April 25th, 2018)
|
## 0.10.1/0.9.7 (April 25th, 2018)
|
||||||
|
|
||||||
|
|
|
@ -388,11 +388,12 @@ func (c *Client) SetAddress(addr string) error {
|
||||||
c.modifyLock.Lock()
|
c.modifyLock.Lock()
|
||||||
defer c.modifyLock.Unlock()
|
defer c.modifyLock.Unlock()
|
||||||
|
|
||||||
var err error
|
parsedAddr, err := url.Parse(addr)
|
||||||
if c.addr, err = url.Parse(addr); err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrapf("failed to set address: {{err}}", err)
|
return errwrap.Wrapf("failed to set address: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.addr = parsedAddr
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +412,8 @@ func (c *Client) SetLimiter(rateLimit float64, burst int) {
|
||||||
c.modifyLock.RLock()
|
c.modifyLock.RLock()
|
||||||
c.config.modifyLock.Lock()
|
c.config.modifyLock.Lock()
|
||||||
defer c.config.modifyLock.Unlock()
|
defer c.config.modifyLock.Unlock()
|
||||||
defer c.modifyLock.RUnlock()
|
c.modifyLock.RUnlock()
|
||||||
|
|
||||||
c.config.Limiter = rate.NewLimiter(rate.Limit(rateLimit), burst)
|
c.config.Limiter = rate.NewLimiter(rate.Limit(rateLimit), burst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,14 +546,20 @@ func (c *Client) SetPolicyOverride(override bool) {
|
||||||
// doesn't need to be called externally.
|
// doesn't need to be called externally.
|
||||||
func (c *Client) NewRequest(method, requestPath string) *Request {
|
func (c *Client) NewRequest(method, requestPath string) *Request {
|
||||||
c.modifyLock.RLock()
|
c.modifyLock.RLock()
|
||||||
defer c.modifyLock.RUnlock()
|
addr := c.addr
|
||||||
|
token := c.token
|
||||||
|
mfaCreds := c.mfaCreds
|
||||||
|
wrappingLookupFunc := c.wrappingLookupFunc
|
||||||
|
headers := c.headers
|
||||||
|
policyOverride := c.policyOverride
|
||||||
|
c.modifyLock.RUnlock()
|
||||||
|
|
||||||
// if SRV records exist (see https://tools.ietf.org/html/draft-andrews-http-srv-02), lookup the SRV
|
// if SRV records exist (see https://tools.ietf.org/html/draft-andrews-http-srv-02), lookup the SRV
|
||||||
// record and take the highest match; this is not designed for high-availability, just discovery
|
// record and take the highest match; this is not designed for high-availability, just discovery
|
||||||
var host string = c.addr.Host
|
var host string = addr.Host
|
||||||
if c.addr.Port() == "" {
|
if addr.Port() == "" {
|
||||||
// Internet Draft specifies that the SRV record is ignored if a port is given
|
// Internet Draft specifies that the SRV record is ignored if a port is given
|
||||||
_, addrs, err := net.LookupSRV("http", "tcp", c.addr.Hostname())
|
_, addrs, err := net.LookupSRV("http", "tcp", addr.Hostname())
|
||||||
if err == nil && len(addrs) > 0 {
|
if err == nil && len(addrs) > 0 {
|
||||||
host = fmt.Sprintf("%s:%d", addrs[0].Target, addrs[0].Port)
|
host = fmt.Sprintf("%s:%d", addrs[0].Target, addrs[0].Port)
|
||||||
}
|
}
|
||||||
|
@ -560,12 +568,12 @@ func (c *Client) NewRequest(method, requestPath string) *Request {
|
||||||
req := &Request{
|
req := &Request{
|
||||||
Method: method,
|
Method: method,
|
||||||
URL: &url.URL{
|
URL: &url.URL{
|
||||||
User: c.addr.User,
|
User: addr.User,
|
||||||
Scheme: c.addr.Scheme,
|
Scheme: addr.Scheme,
|
||||||
Host: host,
|
Host: host,
|
||||||
Path: path.Join(c.addr.Path, requestPath),
|
Path: path.Join(addr.Path, requestPath),
|
||||||
},
|
},
|
||||||
ClientToken: c.token,
|
ClientToken: token,
|
||||||
Params: make(map[string][]string),
|
Params: make(map[string][]string),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,21 +587,19 @@ func (c *Client) NewRequest(method, requestPath string) *Request {
|
||||||
lookupPath = requestPath
|
lookupPath = requestPath
|
||||||
}
|
}
|
||||||
|
|
||||||
req.MFAHeaderVals = c.mfaCreds
|
req.MFAHeaderVals = mfaCreds
|
||||||
|
|
||||||
if c.wrappingLookupFunc != nil {
|
if wrappingLookupFunc != nil {
|
||||||
req.WrapTTL = c.wrappingLookupFunc(method, lookupPath)
|
req.WrapTTL = wrappingLookupFunc(method, lookupPath)
|
||||||
} else {
|
} else {
|
||||||
req.WrapTTL = DefaultWrappingLookupFunc(method, lookupPath)
|
req.WrapTTL = DefaultWrappingLookupFunc(method, lookupPath)
|
||||||
}
|
}
|
||||||
if c.config.Timeout != 0 {
|
|
||||||
c.config.HttpClient.Timeout = c.config.Timeout
|
if headers != nil {
|
||||||
}
|
req.Headers = headers
|
||||||
if c.headers != nil {
|
|
||||||
req.Headers = c.headers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
req.PolicyOverride = c.policyOverride
|
req.PolicyOverride = policyOverride
|
||||||
|
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
@ -602,18 +608,23 @@ func (c *Client) NewRequest(method, requestPath string) *Request {
|
||||||
// a Vault server not configured with this client. This is an advanced operation
|
// a Vault server not configured with this client. This is an advanced operation
|
||||||
// that generally won't need to be called externally.
|
// that generally won't need to be called externally.
|
||||||
func (c *Client) RawRequest(r *Request) (*Response, error) {
|
func (c *Client) RawRequest(r *Request) (*Response, error) {
|
||||||
|
|
||||||
c.modifyLock.RLock()
|
c.modifyLock.RLock()
|
||||||
c.config.modifyLock.RLock()
|
|
||||||
defer c.config.modifyLock.RUnlock()
|
|
||||||
|
|
||||||
if c.config.Limiter != nil {
|
|
||||||
c.config.Limiter.Wait(context.Background())
|
|
||||||
}
|
|
||||||
|
|
||||||
token := c.token
|
token := c.token
|
||||||
|
|
||||||
|
c.config.modifyLock.RLock()
|
||||||
|
limiter := c.config.Limiter
|
||||||
|
maxRetries := c.config.MaxRetries
|
||||||
|
backoff := c.config.Backoff
|
||||||
|
httpClient := c.config.HttpClient
|
||||||
|
timeout := c.config.Timeout
|
||||||
|
c.config.modifyLock.RUnlock()
|
||||||
|
|
||||||
c.modifyLock.RUnlock()
|
c.modifyLock.RUnlock()
|
||||||
|
|
||||||
|
if limiter != nil {
|
||||||
|
limiter.Wait(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
// Sanity check the token before potentially erroring from the API
|
// Sanity check the token before potentially erroring from the API
|
||||||
idx := strings.IndexFunc(token, func(c rune) bool {
|
idx := strings.IndexFunc(token, func(c rune) bool {
|
||||||
return !unicode.IsPrint(c)
|
return !unicode.IsPrint(c)
|
||||||
|
@ -632,16 +643,23 @@ START:
|
||||||
return nil, fmt.Errorf("nil request created")
|
return nil, fmt.Errorf("nil request created")
|
||||||
}
|
}
|
||||||
|
|
||||||
backoff := c.config.Backoff
|
// Set the timeout, if any
|
||||||
|
var cancelFunc context.CancelFunc
|
||||||
|
if timeout != 0 {
|
||||||
|
var ctx context.Context
|
||||||
|
ctx, cancelFunc = context.WithTimeout(context.Background(), timeout)
|
||||||
|
req.Request = req.Request.WithContext(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
if backoff == nil {
|
if backoff == nil {
|
||||||
backoff = retryablehttp.LinearJitterBackoff
|
backoff = retryablehttp.LinearJitterBackoff
|
||||||
}
|
}
|
||||||
|
|
||||||
client := &retryablehttp.Client{
|
client := &retryablehttp.Client{
|
||||||
HTTPClient: c.config.HttpClient,
|
HTTPClient: httpClient,
|
||||||
RetryWaitMin: 1000 * time.Millisecond,
|
RetryWaitMin: 1000 * time.Millisecond,
|
||||||
RetryWaitMax: 1500 * time.Millisecond,
|
RetryWaitMax: 1500 * time.Millisecond,
|
||||||
RetryMax: c.config.MaxRetries,
|
RetryMax: maxRetries,
|
||||||
CheckRetry: retryablehttp.DefaultRetryPolicy,
|
CheckRetry: retryablehttp.DefaultRetryPolicy,
|
||||||
Backoff: backoff,
|
Backoff: backoff,
|
||||||
ErrorHandler: retryablehttp.PassthroughErrorHandler,
|
ErrorHandler: retryablehttp.PassthroughErrorHandler,
|
||||||
|
@ -649,6 +667,9 @@ START:
|
||||||
|
|
||||||
var result *Response
|
var result *Response
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
|
if cancelFunc != nil {
|
||||||
|
cancelFunc()
|
||||||
|
}
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
result = &Response{Response: resp}
|
result = &Response{Response: resp}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -244,22 +243,10 @@ func TestClientTimeoutSetting(t *testing.T) {
|
||||||
defer os.Setenv(EnvVaultClientTimeout, oldClientTimeout)
|
defer os.Setenv(EnvVaultClientTimeout, oldClientTimeout)
|
||||||
config := DefaultConfig()
|
config := DefaultConfig()
|
||||||
config.ReadEnvironment()
|
config.ReadEnvironment()
|
||||||
client, err := NewClient(config)
|
_, err := NewClient(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
_ = client.NewRequest("PUT", "/")
|
|
||||||
if client.config.HttpClient.Timeout != time.Second*10 {
|
|
||||||
t.Fatalf("error setting client timeout using env variable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setting custom client timeout for a new request
|
|
||||||
client.SetClientTimeout(time.Second * 20)
|
|
||||||
_ = client.NewRequest("PUT", "/")
|
|
||||||
if client.config.HttpClient.Timeout != time.Second*20 {
|
|
||||||
t.Fatalf("error setting client timeout using SetClientTimeout")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type roundTripperFunc func(*http.Request) (*http.Response, error)
|
type roundTripperFunc func(*http.Request) (*http.Response, error)
|
||||||
|
|
|
@ -843,9 +843,9 @@ func TestBackend_CertWrites(t *testing.T) {
|
||||||
tc := logicaltest.TestCase{
|
tc := logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
Backend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "aaa", ca1, "foo", "", "", false),
|
testAccStepCert(t, "aaa", ca1, "foo", allowed{}, false),
|
||||||
testAccStepCert(t, "bbb", ca2, "foo", "", "", false),
|
testAccStepCert(t, "bbb", ca2, "foo", allowed{}, false),
|
||||||
testAccStepCert(t, "ccc", ca3, "foo", "", "", true),
|
testAccStepCert(t, "ccc", ca3, "foo", allowed{}, true),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
tc.Steps = append(tc.Steps, testAccStepListCerts(t, []string{"aaa", "bbb"})...)
|
tc.Steps = append(tc.Steps, testAccStepListCerts(t, []string{"aaa", "bbb"})...)
|
||||||
|
@ -866,7 +866,7 @@ func TestBackend_basic_CA(t *testing.T) {
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
Backend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", "", "", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
testAccStepCertLease(t, "web", ca, "foo"),
|
testAccStepCertLease(t, "web", ca, "foo"),
|
||||||
testAccStepCertTTL(t, "web", ca, "foo"),
|
testAccStepCertTTL(t, "web", ca, "foo"),
|
||||||
|
@ -875,9 +875,9 @@ func TestBackend_basic_CA(t *testing.T) {
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
testAccStepCertNoLease(t, "web", ca, "foo"),
|
testAccStepCertNoLease(t, "web", ca, "foo"),
|
||||||
testAccStepLoginDefaultLease(t, connState),
|
testAccStepLoginDefaultLease(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "*.example.com", "", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "*.example.com"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "*.invalid.com", "", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "*.invalid.com"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -926,20 +926,45 @@ func TestBackend_basic_singleCert(t *testing.T) {
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
Backend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", "", "", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "example.com", "", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "invalid", "", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "", "1.2.3.4:invalid", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{ext: "1.2.3.4:invalid"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test a self-signed client with custom extensions (root CA) that is trusted
|
func TestBackend_common_name_singleCert(t *testing.T) {
|
||||||
func TestBackend_extensions_singleCert(t *testing.T) {
|
connState, err := testConnState("test-fixtures/root/rootcacert.pem",
|
||||||
|
"test-fixtures/root/rootcakey.pem", "test-fixtures/root/rootcacert.pem")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error testing connection state: %v", err)
|
||||||
|
}
|
||||||
|
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
|
Backend: testFactory(t),
|
||||||
|
Steps: []logicaltest.TestStep{
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{}, false),
|
||||||
|
testAccStepLogin(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{common_names: "example.com"}, false),
|
||||||
|
testAccStepLogin(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{common_names: "invalid"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{ext: "1.2.3.4:invalid"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test a self-signed client with custom ext (root CA) that is trusted
|
||||||
|
func TestBackend_ext_singleCert(t *testing.T) {
|
||||||
connState, err := testConnState(
|
connState, err := testConnState(
|
||||||
"test-fixtures/root/rootcawextcert.pem",
|
"test-fixtures/root/rootcawextcert.pem",
|
||||||
"test-fixtures/root/rootcawextkey.pem",
|
"test-fixtures/root/rootcawextkey.pem",
|
||||||
|
@ -955,39 +980,132 @@ func TestBackend_extensions_singleCert(t *testing.T) {
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
Backend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:A UTF8String Extension", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:A UTF8String Extension"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:*,2.1.1.2:A UTF8*", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:*,2.1.1.2:A UTF8*"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "", "1.2.3.45:*", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{ext: "1.2.3.45:*"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:The Wrong Value", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:The Wrong Value"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:*,2.1.1.2:The Wrong Value", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:*,2.1.1.2:The Wrong Value"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:,2.1.1.2:*", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:,2.1.1.2:*"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "example.com", "2.1.1.1:A UTF8String Extension", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com", ext: "2.1.1.1:A UTF8String Extension"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "example.com", "2.1.1.1:*,2.1.1.2:A UTF8*", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com", ext: "2.1.1.1:*,2.1.1.2:A UTF8*"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "example.com", "1.2.3.45:*", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com", ext: "1.2.3.45:*"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "example.com", "2.1.1.1:The Wrong Value", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com", ext: "2.1.1.1:The Wrong Value"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "example.com", "2.1.1.1:*,2.1.1.2:The Wrong Value", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com", ext: "2.1.1.1:*,2.1.1.2:The Wrong Value"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "invalid", "2.1.1.1:A UTF8String Extension", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid", ext: "2.1.1.1:A UTF8String Extension"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "invalid", "2.1.1.1:*,2.1.1.2:A UTF8*", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid", ext: "2.1.1.1:*,2.1.1.2:A UTF8*"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "invalid", "1.2.3.45:*", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid", ext: "1.2.3.45:*"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "invalid", "2.1.1.1:The Wrong Value", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid", ext: "2.1.1.1:The Wrong Value"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
testAccStepCert(t, "web", ca, "foo", "invalid", "2.1.1.1:*,2.1.1.2:The Wrong Value", false),
|
testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid", ext: "2.1.1.1:*,2.1.1.2:The Wrong Value"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test a self-signed client with URI alt names (root CA) that is trusted
|
||||||
|
func TestBackend_dns_singleCert(t *testing.T) {
|
||||||
|
connState, err := testConnState(
|
||||||
|
"test-fixtures/root/rootcawdnscert.pem",
|
||||||
|
"test-fixtures/root/rootcawdnskey.pem",
|
||||||
|
"test-fixtures/root/rootcacert.pem",
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error testing connection state: %v", err)
|
||||||
|
}
|
||||||
|
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
|
Backend: testFactory(t),
|
||||||
|
Steps: []logicaltest.TestStep{
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{dns: "example.com"}, false),
|
||||||
|
testAccStepLogin(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{dns: "*ample.com"}, false),
|
||||||
|
testAccStepLogin(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{dns: "notincert.com"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{dns: "abc"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{dns: "*.example.com"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test a self-signed client with URI alt names (root CA) that is trusted
|
||||||
|
func TestBackend_email_singleCert(t *testing.T) {
|
||||||
|
connState, err := testConnState(
|
||||||
|
"test-fixtures/root/rootcawemailcert.pem",
|
||||||
|
"test-fixtures/root/rootcawemailkey.pem",
|
||||||
|
"test-fixtures/root/rootcacert.pem",
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error testing connection state: %v", err)
|
||||||
|
}
|
||||||
|
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
|
Backend: testFactory(t),
|
||||||
|
Steps: []logicaltest.TestStep{
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{emails: "valid@example.com"}, false),
|
||||||
|
testAccStepLogin(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{emails: "*@example.com"}, false),
|
||||||
|
testAccStepLogin(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{emails: "invalid@notincert.com"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{emails: "abc"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{emails: "*.example.com"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test a self-signed client with URI alt names (root CA) that is trusted
|
||||||
|
func TestBackend_uri_singleCert(t *testing.T) {
|
||||||
|
connState, err := testConnState(
|
||||||
|
"test-fixtures/root/rootcawuricert.pem",
|
||||||
|
"test-fixtures/root/rootcawurikey.pem",
|
||||||
|
"test-fixtures/root/rootcacert.pem",
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error testing connection state: %v", err)
|
||||||
|
}
|
||||||
|
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
|
Backend: testFactory(t),
|
||||||
|
Steps: []logicaltest.TestStep{
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{uris: "spiffe://example.com/*"}, false),
|
||||||
|
testAccStepLogin(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{uris: "spiffe://example.com/host"}, false),
|
||||||
|
testAccStepLogin(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{uris: "spiffe://example.com/invalid"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{uris: "abc"}, false),
|
||||||
|
testAccStepLoginInvalid(t, connState),
|
||||||
|
testAccStepCert(t, "web", ca, "foo", allowed{uris: "http://www.google.com"}, false),
|
||||||
testAccStepLoginInvalid(t, connState),
|
testAccStepLoginInvalid(t, connState),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1007,9 +1125,9 @@ func TestBackend_mixed_constraints(t *testing.T) {
|
||||||
logicaltest.Test(t, logicaltest.TestCase{
|
logicaltest.Test(t, logicaltest.TestCase{
|
||||||
Backend: testFactory(t),
|
Backend: testFactory(t),
|
||||||
Steps: []logicaltest.TestStep{
|
Steps: []logicaltest.TestStep{
|
||||||
testAccStepCert(t, "1unconstrained", ca, "foo", "", "", false),
|
testAccStepCert(t, "1unconstrained", ca, "foo", allowed{}, false),
|
||||||
testAccStepCert(t, "2matching", ca, "foo", "*.example.com,whatever", "", false),
|
testAccStepCert(t, "2matching", ca, "foo", allowed{names: "*.example.com,whatever"}, false),
|
||||||
testAccStepCert(t, "3invalid", ca, "foo", "invalid", "", false),
|
testAccStepCert(t, "3invalid", ca, "foo", allowed{names: "invalid"}, false),
|
||||||
testAccStepLogin(t, connState),
|
testAccStepLogin(t, connState),
|
||||||
// Assumes CertEntries are processed in alphabetical order (due to store.List), so we only match 2matching if 1unconstrained doesn't match
|
// Assumes CertEntries are processed in alphabetical order (due to store.List), so we only match 2matching if 1unconstrained doesn't match
|
||||||
testAccStepLoginWithName(t, connState, "2matching"),
|
testAccStepLoginWithName(t, connState, "2matching"),
|
||||||
|
@ -1314,8 +1432,17 @@ func testAccStepListCerts(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type allowed struct {
|
||||||
|
names string // allowed names in the certificate, looks at common, name, dns, email [depricated]
|
||||||
|
common_names string // allowed common names in the certificate
|
||||||
|
dns string // allowed dns names in the SAN extension of the certificate
|
||||||
|
emails string // allowed email names in SAN extension of the certificate
|
||||||
|
uris string // allowed uris in SAN extension of the certificate
|
||||||
|
ext string // required extensions in the certificate
|
||||||
|
}
|
||||||
|
|
||||||
func testAccStepCert(
|
func testAccStepCert(
|
||||||
t *testing.T, name string, cert []byte, policies string, allowedNames string, requiredExtensions string, expectError bool) logicaltest.TestStep {
|
t *testing.T, name string, cert []byte, policies string, testData allowed, expectError bool) logicaltest.TestStep {
|
||||||
return logicaltest.TestStep{
|
return logicaltest.TestStep{
|
||||||
Operation: logical.UpdateOperation,
|
Operation: logical.UpdateOperation,
|
||||||
Path: "certs/" + name,
|
Path: "certs/" + name,
|
||||||
|
@ -1324,8 +1451,12 @@ func testAccStepCert(
|
||||||
"certificate": string(cert),
|
"certificate": string(cert),
|
||||||
"policies": policies,
|
"policies": policies,
|
||||||
"display_name": name,
|
"display_name": name,
|
||||||
"allowed_names": allowedNames,
|
"allowed_names": testData.names,
|
||||||
"required_extensions": requiredExtensions,
|
"allowed_common_names": testData.common_names,
|
||||||
|
"allowed_dns_sans": testData.dns,
|
||||||
|
"allowed_email_sans": testData.emails,
|
||||||
|
"allowed_uri_sans": testData.uris,
|
||||||
|
"required_extensions": testData.ext,
|
||||||
"lease": 1000,
|
"lease": 1000,
|
||||||
},
|
},
|
||||||
Check: func(resp *logical.Response) error {
|
Check: func(resp *logical.Response) error {
|
||||||
|
|
|
@ -45,7 +45,33 @@ Must be x509 PEM encoded.`,
|
||||||
"allowed_names": &framework.FieldSchema{
|
"allowed_names": &framework.FieldSchema{
|
||||||
Type: framework.TypeCommaStringSlice,
|
Type: framework.TypeCommaStringSlice,
|
||||||
Description: `A comma-separated list of names.
|
Description: `A comma-separated list of names.
|
||||||
At least one must exist in either the Common Name or SANs. Supports globbing.`,
|
At least one must exist in either the Common Name or SANs. Supports globbing.
|
||||||
|
This parameter is deprecated, please use allowed_common_names, allowed_dns_sans,
|
||||||
|
allowed_email_sans, allowed_uri_sans.`,
|
||||||
|
},
|
||||||
|
|
||||||
|
"allowed_common_names": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeCommaStringSlice,
|
||||||
|
Description: `A comma-separated list of names.
|
||||||
|
At least one must exist in the Common Name. Supports globbing.`,
|
||||||
|
},
|
||||||
|
|
||||||
|
"allowed_dns_sans": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeCommaStringSlice,
|
||||||
|
Description: `A comma-separated list of DNS names.
|
||||||
|
At least one must exist in the SANs. Supports globbing.`,
|
||||||
|
},
|
||||||
|
|
||||||
|
"allowed_email_sans": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeCommaStringSlice,
|
||||||
|
Description: `A comma-separated list of Email Addresses.
|
||||||
|
At least one must exist in the SANs. Supports globbing.`,
|
||||||
|
},
|
||||||
|
|
||||||
|
"allowed_uri_sans": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeCommaStringSlice,
|
||||||
|
Description: `A comma-separated list of URIs.
|
||||||
|
At least one must exist in the SANs. Supports globbing.`,
|
||||||
},
|
},
|
||||||
|
|
||||||
"required_extensions": &framework.FieldSchema{
|
"required_extensions": &framework.FieldSchema{
|
||||||
|
@ -77,12 +103,14 @@ seconds. Defaults to system/backend default TTL.`,
|
||||||
Description: `TTL for tokens issued by this backend.
|
Description: `TTL for tokens issued by this backend.
|
||||||
Defaults to system/backend default TTL time.`,
|
Defaults to system/backend default TTL time.`,
|
||||||
},
|
},
|
||||||
|
|
||||||
"max_ttl": &framework.FieldSchema{
|
"max_ttl": &framework.FieldSchema{
|
||||||
Type: framework.TypeDurationSecond,
|
Type: framework.TypeDurationSecond,
|
||||||
Description: `Duration in either an integer number of seconds (3600) or
|
Description: `Duration in either an integer number of seconds (3600) or
|
||||||
an integer time unit (60m) after which the
|
an integer time unit (60m) after which the
|
||||||
issued token can no longer be renewed.`,
|
issued token can no longer be renewed.`,
|
||||||
},
|
},
|
||||||
|
|
||||||
"period": &framework.FieldSchema{
|
"period": &framework.FieldSchema{
|
||||||
Type: framework.TypeDurationSecond,
|
Type: framework.TypeDurationSecond,
|
||||||
Description: `If set, indicates that the token generated using this role
|
Description: `If set, indicates that the token generated using this role
|
||||||
|
@ -158,6 +186,11 @@ func (b *backend) pathCertRead(ctx context.Context, req *logical.Request, d *fra
|
||||||
"max_ttl": cert.MaxTTL / time.Second,
|
"max_ttl": cert.MaxTTL / time.Second,
|
||||||
"period": cert.Period / time.Second,
|
"period": cert.Period / time.Second,
|
||||||
"allowed_names": cert.AllowedNames,
|
"allowed_names": cert.AllowedNames,
|
||||||
|
"allowed_common_names": cert.AllowedCommonNames,
|
||||||
|
"allowed_dns_sans": cert.AllowedDNSSANs,
|
||||||
|
"allowed_email_sans": cert.AllowedEmailSANs,
|
||||||
|
"allowed_uri_sans": cert.AllowedURISANs,
|
||||||
|
"required_extensions": cert.RequiredExtensions,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -168,6 +201,10 @@ func (b *backend) pathCertWrite(ctx context.Context, req *logical.Request, d *fr
|
||||||
displayName := d.Get("display_name").(string)
|
displayName := d.Get("display_name").(string)
|
||||||
policies := policyutil.ParsePolicies(d.Get("policies"))
|
policies := policyutil.ParsePolicies(d.Get("policies"))
|
||||||
allowedNames := d.Get("allowed_names").([]string)
|
allowedNames := d.Get("allowed_names").([]string)
|
||||||
|
allowedCommonNames := d.Get("allowed_common_names").([]string)
|
||||||
|
allowedDNSSANs := d.Get("allowed_dns_sans").([]string)
|
||||||
|
allowedEmailSANs := d.Get("allowed_email_sans").([]string)
|
||||||
|
allowedURISANs := d.Get("allowed_uri_sans").([]string)
|
||||||
requiredExtensions := d.Get("required_extensions").([]string)
|
requiredExtensions := d.Get("required_extensions").([]string)
|
||||||
|
|
||||||
var resp logical.Response
|
var resp logical.Response
|
||||||
|
@ -246,6 +283,10 @@ func (b *backend) pathCertWrite(ctx context.Context, req *logical.Request, d *fr
|
||||||
DisplayName: displayName,
|
DisplayName: displayName,
|
||||||
Policies: policies,
|
Policies: policies,
|
||||||
AllowedNames: allowedNames,
|
AllowedNames: allowedNames,
|
||||||
|
AllowedCommonNames: allowedCommonNames,
|
||||||
|
AllowedDNSSANs: allowedDNSSANs,
|
||||||
|
AllowedEmailSANs: allowedEmailSANs,
|
||||||
|
AllowedURISANs: allowedURISANs,
|
||||||
RequiredExtensions: requiredExtensions,
|
RequiredExtensions: requiredExtensions,
|
||||||
TTL: ttl,
|
TTL: ttl,
|
||||||
MaxTTL: maxTTL,
|
MaxTTL: maxTTL,
|
||||||
|
@ -278,6 +319,10 @@ type CertEntry struct {
|
||||||
MaxTTL time.Duration
|
MaxTTL time.Duration
|
||||||
Period time.Duration
|
Period time.Duration
|
||||||
AllowedNames []string
|
AllowedNames []string
|
||||||
|
AllowedCommonNames []string
|
||||||
|
AllowedDNSSANs []string
|
||||||
|
AllowedEmailSANs []string
|
||||||
|
AllowedURISANs []string
|
||||||
RequiredExtensions []string
|
RequiredExtensions []string
|
||||||
BoundCIDRs []*sockaddr.SockAddrMarshaler
|
BoundCIDRs []*sockaddr.SockAddrMarshaler
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,6 +253,10 @@ func (b *backend) verifyCredentials(ctx context.Context, req *logical.Request, d
|
||||||
func (b *backend) matchesConstraints(clientCert *x509.Certificate, trustedChain []*x509.Certificate, config *ParsedCert) bool {
|
func (b *backend) matchesConstraints(clientCert *x509.Certificate, trustedChain []*x509.Certificate, config *ParsedCert) bool {
|
||||||
return !b.checkForChainInCRLs(trustedChain) &&
|
return !b.checkForChainInCRLs(trustedChain) &&
|
||||||
b.matchesNames(clientCert, config) &&
|
b.matchesNames(clientCert, config) &&
|
||||||
|
b.matchesCommonName(clientCert, config) &&
|
||||||
|
b.matchesDNSSANs(clientCert, config) &&
|
||||||
|
b.matchesEmailSANs(clientCert, config) &&
|
||||||
|
b.matchesURISANs(clientCert, config) &&
|
||||||
b.matchesCertificateExtensions(clientCert, config)
|
b.matchesCertificateExtensions(clientCert, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,10 +284,85 @@ func (b *backend) matchesNames(clientCert *x509.Certificate, config *ParsedCert)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// matchesCommonName verifies that the certificate matches at least one configured
|
||||||
|
// allowed common name
|
||||||
|
func (b *backend) matchesCommonName(clientCert *x509.Certificate, config *ParsedCert) bool {
|
||||||
|
// Default behavior (no names) is to allow all names
|
||||||
|
if len(config.Entry.AllowedCommonNames) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// At least one pattern must match at least one name if any patterns are specified
|
||||||
|
for _, allowedCommonName := range config.Entry.AllowedCommonNames {
|
||||||
|
if glob.Glob(allowedCommonName, clientCert.Subject.CommonName) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// matchesDNSSANs verifies that the certificate matches at least one configured
|
||||||
|
// allowed dns entry in the subject alternate name extension
|
||||||
|
func (b *backend) matchesDNSSANs(clientCert *x509.Certificate, config *ParsedCert) bool {
|
||||||
|
// Default behavior (no names) is to allow all names
|
||||||
|
if len(config.Entry.AllowedDNSSANs) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// At least one pattern must match at least one name if any patterns are specified
|
||||||
|
for _, allowedDNS := range config.Entry.AllowedDNSSANs {
|
||||||
|
for _, name := range clientCert.DNSNames {
|
||||||
|
if glob.Glob(allowedDNS, name) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// matchesEmailSANs verifies that the certificate matches at least one configured
|
||||||
|
// allowed email in the subject alternate name extension
|
||||||
|
func (b *backend) matchesEmailSANs(clientCert *x509.Certificate, config *ParsedCert) bool {
|
||||||
|
// Default behavior (no names) is to allow all names
|
||||||
|
if len(config.Entry.AllowedEmailSANs) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// At least one pattern must match at least one name if any patterns are specified
|
||||||
|
for _, allowedEmail := range config.Entry.AllowedEmailSANs {
|
||||||
|
for _, email := range clientCert.EmailAddresses {
|
||||||
|
if glob.Glob(allowedEmail, email) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// matchesURISANs verifies that the certificate matches at least one configured
|
||||||
|
// allowed uri in the subject alternate name extension
|
||||||
|
func (b *backend) matchesURISANs(clientCert *x509.Certificate, config *ParsedCert) bool {
|
||||||
|
// Default behavior (no names) is to allow all names
|
||||||
|
if len(config.Entry.AllowedURISANs) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// At least one pattern must match at least one name if any patterns are specified
|
||||||
|
for _, allowedURI := range config.Entry.AllowedURISANs {
|
||||||
|
for _, name := range clientCert.URIs {
|
||||||
|
if glob.Glob(allowedURI, name.String()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// matchesCertificateExtensions verifies that the certificate matches configured
|
// matchesCertificateExtensions verifies that the certificate matches configured
|
||||||
// required extensions
|
// required extensions
|
||||||
func (b *backend) matchesCertificateExtensions(clientCert *x509.Certificate, config *ParsedCert) bool {
|
func (b *backend) matchesCertificateExtensions(clientCert *x509.Certificate, config *ParsedCert) bool {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
92223EAFBBEE17A3
|
92223EAFBBEE17AF
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
[ req ]
|
||||||
|
default_bits = 2048
|
||||||
|
encrypt_key = no
|
||||||
|
prompt = no
|
||||||
|
default_md = sha256
|
||||||
|
req_extensions = req_v3
|
||||||
|
distinguished_name = dn
|
||||||
|
|
||||||
|
[ dn ]
|
||||||
|
CN = example.com
|
||||||
|
|
||||||
|
[ req_v3 ]
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
|
||||||
|
[ alt_names ]
|
||||||
|
IP.1 = 127.0.0.1
|
||||||
|
DNS.1 = example.com
|
|
@ -0,0 +1,27 @@
|
||||||
|
-----BEGIN CERTIFICATE REQUEST-----
|
||||||
|
MIIEijCCAnICAQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3
|
||||||
|
DQEBAQUAA4ICDwAwggIKAoICAQDUJ6s97BFxR295bCjpwQ85Vo8DnBFa/awNH107
|
||||||
|
QFn/zw0ZDdJMLtEBc/bw7pTYw5ulKbiZDFrmzPEY+QZlo+t1TeWgPRJg0CbYNukS
|
||||||
|
aNv0vKXjDXYwbrCyOvZucy8hte6IKjZfH+kAsgbbUxfD75BCKsxMxbVHkg0W9Ma2
|
||||||
|
pnZj/kpvQE5lkMj5mDvtWdfCRsVg4zL6jhRHkPZ6fOkF3mrfTbQu3oyOcbKLEE/G
|
||||||
|
t3QRKw3uv0vMDmhg62ZPvD1k70UMjUV2MVqEPZuWY7/bbW8OsfzMyBOGY9LLp7QS
|
||||||
|
krxWYRj6SPUR4f1bZq7pRbqOfS0okq/XDLf1k6Na5cT6iNdyjEVdSJl7vR7kSreX
|
||||||
|
8hkwK46Oup8v/vJLu/cRDCpAas0gJJkJDPt5114V0/Xww7EFxs5GijXP8i5RLlgK
|
||||||
|
/nRscbK+fgjQOnQ5cp0pcP8HAriy2vil7E0fQvMvt5QTyINEYgiYaCIT9WGRC8Xo
|
||||||
|
WcoUGI2vyrGy6RU6A3/TKeBLtikaSPjFKa1dFTAHfrUkTBpfqc+sbiJ334Bvucg5
|
||||||
|
WyS8oAC5Vf++iMnETSdzx1k0/QARVLD38PO8wPaPU1M2XaSA+RHTB9SGFc4VTauT
|
||||||
|
B167NLlmgJHYuhp+KM1RTy1TEoDlJh2qKj21BLcR1GJ0KgDze6Vpf9xdRTdqMpo2
|
||||||
|
h20wdQIDAQABoC8wLQYJKoZIhvcNAQkOMSAwHjAcBgNVHREEFTAThwR/AAABggtl
|
||||||
|
eGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAGtds+2IUVKzw9bi130mBbb9K
|
||||||
|
CrXw2NXSp+LJwneIEy0bjAaNr7zCGQsj7q57qFwjc7vLTtGRheP5myrAOq00lp8J
|
||||||
|
1sGZSETS/y4yeITLZSYWVq2dtF/hY9I+X3uOoibdsQgzYqhBcUr4oTDapf1ZEs0i
|
||||||
|
wA2J5IcasfaBpWFc9wRN79BBACLGyCbX6VwUISrGe3Hgzkeqtg97cU62ecQsgXiZ
|
||||||
|
LdQgERvC0wSfAmI4lGulXi1oYYSRxXQ8pEKEAMeJrJVQfvhdbS/o4Bdf3Yj6ibtD
|
||||||
|
tFSdKLcdRCfMQBEHNpSh665LfBbwU55Fh89tBdGmf6uqsimUY6AxNncnLsc1Kq6F
|
||||||
|
oINXix3GsBNmCahDeHdGOlNjw0Lpl0m6bnu6LXSDwwuNWAEdDfEmxR+5T/GkGxcG
|
||||||
|
TTWPwEkpnCe4VmGl9Y10uPSvqneNsdNWjDVK4BeW4VSf9Lp1Zeme1dYFvpyzow+r
|
||||||
|
4ogpvMPf5vy5I/0HCEf1KlaPyhs8ZGK6YBGaeEDYSaysAWJfYm8eiqwUuKYj/FUe
|
||||||
|
G3KkaFpOGsQHFNRtG8GukV3r2AK97HFHKNfygZ2xvk5isXz2ZsNX1/J0+GGjalJl
|
||||||
|
cWBBEiXFM94XJHE9rACsL2UKn8cWCh9lHNLlePOkQuoNY9CUd63xx4Hg97XWP3+U
|
||||||
|
DhpG7CADsKcPJfbMgrk=
|
||||||
|
-----END CERTIFICATE REQUEST-----
|
|
@ -0,0 +1,23 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDzzCCAregAwIBAgIJAJIiPq+77herMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV
|
||||||
|
BAMTC2V4YW1wbGUuY29tMB4XDTE4MDQyNjEyMDEzMFoXDTE5MDQyNjEyMDEzMFow
|
||||||
|
FjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
|
||||||
|
ggIKAoICAQDUJ6s97BFxR295bCjpwQ85Vo8DnBFa/awNH107QFn/zw0ZDdJMLtEB
|
||||||
|
c/bw7pTYw5ulKbiZDFrmzPEY+QZlo+t1TeWgPRJg0CbYNukSaNv0vKXjDXYwbrCy
|
||||||
|
OvZucy8hte6IKjZfH+kAsgbbUxfD75BCKsxMxbVHkg0W9Ma2pnZj/kpvQE5lkMj5
|
||||||
|
mDvtWdfCRsVg4zL6jhRHkPZ6fOkF3mrfTbQu3oyOcbKLEE/Gt3QRKw3uv0vMDmhg
|
||||||
|
62ZPvD1k70UMjUV2MVqEPZuWY7/bbW8OsfzMyBOGY9LLp7QSkrxWYRj6SPUR4f1b
|
||||||
|
Zq7pRbqOfS0okq/XDLf1k6Na5cT6iNdyjEVdSJl7vR7kSreX8hkwK46Oup8v/vJL
|
||||||
|
u/cRDCpAas0gJJkJDPt5114V0/Xww7EFxs5GijXP8i5RLlgK/nRscbK+fgjQOnQ5
|
||||||
|
cp0pcP8HAriy2vil7E0fQvMvt5QTyINEYgiYaCIT9WGRC8XoWcoUGI2vyrGy6RU6
|
||||||
|
A3/TKeBLtikaSPjFKa1dFTAHfrUkTBpfqc+sbiJ334Bvucg5WyS8oAC5Vf++iMnE
|
||||||
|
TSdzx1k0/QARVLD38PO8wPaPU1M2XaSA+RHTB9SGFc4VTauTB167NLlmgJHYuhp+
|
||||||
|
KM1RTy1TEoDlJh2qKj21BLcR1GJ0KgDze6Vpf9xdRTdqMpo2h20wdQIDAQABoyAw
|
||||||
|
HjAcBgNVHREEFTAThwR/AAABggtleGFtcGxlLmNvbTANBgkqhkiG9w0BAQUFAAOC
|
||||||
|
AQEA2JswcCYtHvOm2QmSEVeFcCeVNkzr35FXATamJv0oMMjjUFix78MW03EW6vJa
|
||||||
|
E52e3pBvRdy+k2fuq/RtHIUKzB6jNbv0Vds26Dq+pmGeoaQZOW94/Wht7f9pZgBi
|
||||||
|
IRPBg9oACtyNAuDsCOdetOyvyoU29sjUOUoQZbEXF+FK4lRJrEmZUJHbp/BOD58V
|
||||||
|
mQRtjTMjQlZZropqBQmooMRYU0qgWHaIjyoQpu2MgEj3+/1b1IX6SCfRuit0auh/
|
||||||
|
YI3/cCtyAG/DpZ6zfyXuyY+iN+l8B6t0nXyV3g8JgBWYPGJv1hgVIgnnqlwuL517
|
||||||
|
mEAT5RnHCNJQNuzS1dwfuBrX3w==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,52 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDUJ6s97BFxR295
|
||||||
|
bCjpwQ85Vo8DnBFa/awNH107QFn/zw0ZDdJMLtEBc/bw7pTYw5ulKbiZDFrmzPEY
|
||||||
|
+QZlo+t1TeWgPRJg0CbYNukSaNv0vKXjDXYwbrCyOvZucy8hte6IKjZfH+kAsgbb
|
||||||
|
UxfD75BCKsxMxbVHkg0W9Ma2pnZj/kpvQE5lkMj5mDvtWdfCRsVg4zL6jhRHkPZ6
|
||||||
|
fOkF3mrfTbQu3oyOcbKLEE/Gt3QRKw3uv0vMDmhg62ZPvD1k70UMjUV2MVqEPZuW
|
||||||
|
Y7/bbW8OsfzMyBOGY9LLp7QSkrxWYRj6SPUR4f1bZq7pRbqOfS0okq/XDLf1k6Na
|
||||||
|
5cT6iNdyjEVdSJl7vR7kSreX8hkwK46Oup8v/vJLu/cRDCpAas0gJJkJDPt5114V
|
||||||
|
0/Xww7EFxs5GijXP8i5RLlgK/nRscbK+fgjQOnQ5cp0pcP8HAriy2vil7E0fQvMv
|
||||||
|
t5QTyINEYgiYaCIT9WGRC8XoWcoUGI2vyrGy6RU6A3/TKeBLtikaSPjFKa1dFTAH
|
||||||
|
frUkTBpfqc+sbiJ334Bvucg5WyS8oAC5Vf++iMnETSdzx1k0/QARVLD38PO8wPaP
|
||||||
|
U1M2XaSA+RHTB9SGFc4VTauTB167NLlmgJHYuhp+KM1RTy1TEoDlJh2qKj21BLcR
|
||||||
|
1GJ0KgDze6Vpf9xdRTdqMpo2h20wdQIDAQABAoICAQDJxszUQQC554I7TsZ+xBJx
|
||||||
|
q0Sr3zSWgOuxM2Jdpy+x38AKUx3vPRulsSBtN8yzeR9Ab7TVQ231U3f/E2GlK8kW
|
||||||
|
sTazN0KSd4ZqX5c+3iJM21s+3p/JIo3FhdS5aa2q9zjdoqBByry135wr3xScUu22
|
||||||
|
MLRMVEG8x0jRy45vS1UQd1teAiBN8u1ijgp5DNjrOpohMxVaPeVFx7bU+pY58bdd
|
||||||
|
mK7FYP73v2VbY/EsA3FNntBKgQBbHFzjyR9uuI7/v53BeV9WMUxwt5OR7l8cGDHn
|
||||||
|
HRtdvPDtAWYMMf1PKOYdlY3HBbqn/nMUCk5TKPFs8dsQWqsI8lzIIVndauj0i0+0
|
||||||
|
M/lVMXu4x48o5FfLa4HjkpcDxAU6QDHA9thaDkasZebixVH/p1ZJkLORl5jDLYkU
|
||||||
|
Av+B3i1efITwNYgosZNjPpw0PyYh9PV9JvB87d5wFpgISfZyRXpBVGeJbt6gg++8
|
||||||
|
8/5A/GzSpGy0FhLcP3vuVTcX2VOexjqeaoi4U3cHrbWv/wNj5a4BNk5EJT8fVeSb
|
||||||
|
+Emqydl9u3n2E315GPC8kwxdE3r3hGrWdZQn9byGvqzwDaLWXQLQWvQN4GOpGTrP
|
||||||
|
Yxj2Oi8s1MJHkppj4eo52O4J7cBlAJn3RFmlCKGOoWJZMdPktp/gWeT+xIGSaa21
|
||||||
|
qB+l/ZFEWLPMxdTBMGFmYQKCAQEA8DgozaZBXr7mb1H25EbW9YmtLc61JMapQrZb
|
||||||
|
ObygiGR6RZsxCXEvGdhvvmwpO8rA9wAOWqI8NV5GU8EvuRuwvGoX4HqbXkB6ZcyC
|
||||||
|
6RuZzki2lrKVGUaLc1v6MyhX4IzrqTYWDgQvwd9lMcUGR7r007KPE5ft4v3/TuxQ
|
||||||
|
qPKxQE7NO2xnTloUchd5g0/d975GZi0g6XDecFOuj43Pi0c/wRcFH6zfVirdcm+M
|
||||||
|
yP9CsJ/LUgtV1voLqyhfybwHvzpxJ0l25Fw+P85I4czosBp+FaFAwogxZEDnY8Fr
|
||||||
|
Hqcwdc7vwGDjTbtflDsUdppt2h8nD8bBZGysG8+P8HAt3i5D+QKCAQEA4heKueRQ
|
||||||
|
Y8nTZlmRSRtB6usRAeymQBJjO+yWwu/06Efg8VW5QRwtP0sx+syrLaQDy8MT07II
|
||||||
|
XQZmq55xATWbHCxULiceIY2KG5LHCovVotYAll8ov58exJva19C7/41uVrkl3H9j
|
||||||
|
xFLX0Bn3zMFKBOxKhygP2xqqEJdb1JJt27c2CbXvXOzqIZ4RCaNQdBdrlEiXQihR
|
||||||
|
JCGMUBfrYIwALQFzYuPGULhg77YcAi5owCPnfK+dDOOvMmW8BwPnRUc14WFIVV+m
|
||||||
|
dbY22WonLNPP055W5755Xl9RHKW1bcmIH6E4QZpMrlnd1UzPBQq1PJtcO3uRc5T6
|
||||||
|
CMQSUmwMGSQ3XQKCAQBiuVHborY+8AnYOkFTc+GoK5rmtosvwA2UA0neoqz/IPw3
|
||||||
|
Wx5+GOwYnSDfi6gukJdZa8Z6bS59aG9SwJSSaNTrulZxxTHRPIKRD8nFb7h4VN3l
|
||||||
|
dSNdreZl1KkxGSV0fbXkZvwNap8N+HeoSqbYF/fCgSHYFZqIrYadsvU7WfKK0Vf7
|
||||||
|
UgPq6Y55jTg9RTeeN67LE0Txa5efZmTZTpi7Tt7exk0uxWdMDHXSMBIWEQIhgKqY
|
||||||
|
31u57C2bfA5R5FrytlwGn2SjWV2j7214jzQaG+kxjoIE8OALqbjvAHC7uk5qPE/A
|
||||||
|
KpGAQr93Ngik7baz7BWroC2eziK1k0o+sHvJUg5RAoIBABF+ftZ5axr9j+T4gzxj
|
||||||
|
5orV24AJnqeQhKsrWFMHHC0o+qfR2T7HflzKZbihQ5GJgl2u34be3LTN/P3Eibvt
|
||||||
|
OO5KI81aa4NvH0OY7NvNDB/IbU01WcLR/iB6asmONi3E9MezFdHk7YRQYLCSgdEP
|
||||||
|
F7ofyniAyhFLE+OqwolFN0jr+TtxH29SSZ+GSo0zXNNOyJ01rLaKxhSEoAXGhAj5
|
||||||
|
bD4PQa1iMIMocR+7OJmWm7ZaUNwd/onzyCefJZhpXejHZMzmqSEqAIhVLBNQmm1m
|
||||||
|
iks2kkTmQR/jQjR0QgCXunewEtlIpixLedW6Vr5uIK3q240it5N48IvjGAPWpmz/
|
||||||
|
l2UCggEBALRlARlBdYcPhWbcyhq9suq2PJqHVvNdP9vVTZpPgmWgxmj9mPQ731Q/
|
||||||
|
UpRlBIk6U0qAxBXP9kzPqSivWhY8Jto80Jdr+/80PkdANDkpnXoDlxPk095sD2uN
|
||||||
|
Jv5FffFgMZH9MGpPTEuZ571/YtVi+1qFt0i3oazpF/g8gU23f2oxaX4xzsltVl8J
|
||||||
|
rWXYzmYE0i5Qiy81+zZ9dZlnmlKhcYpD6m2t/0hRAoNaoxOUV7WFcIzYIxpKvzYL
|
||||||
|
QTDL/Se2Ooc0xLQvM1oZ9/1NE2hpGQ/ipASEPlx9KO5ktYW7+LwdcSCMXtx84I/D
|
||||||
|
VQpWjPdILMpiVrB/9NsENTNv2DUvc+o=
|
||||||
|
-----END PRIVATE KEY-----
|
|
@ -0,0 +1,17 @@
|
||||||
|
[ req ]
|
||||||
|
default_bits = 2048
|
||||||
|
encrypt_key = no
|
||||||
|
prompt = no
|
||||||
|
default_md = sha256
|
||||||
|
distinguished_name = dn
|
||||||
|
req_extensions = req_v3
|
||||||
|
|
||||||
|
[ req_v3 ]
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
|
||||||
|
[ dn ]
|
||||||
|
CN = example.com
|
||||||
|
|
||||||
|
[ alt_names ]
|
||||||
|
IP.1 = 127.0.0.1
|
||||||
|
email = valid@example.com
|
|
@ -0,0 +1,27 @@
|
||||||
|
-----BEGIN CERTIFICATE REQUEST-----
|
||||||
|
MIIEkDCCAngCAQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3
|
||||||
|
DQEBAQUAA4ICDwAwggIKAoICAQDO7stcdJQwUtVeJriwpAswDAirO827peSlgdxs
|
||||||
|
fW8X9M2hE9ihvESEILb7TRMRiFlDyQYg1BxKMrJ0DZmixFi8RvUCZbH6TFOUMsk+
|
||||||
|
w1FhpzjuqAqxNQ51s7u30sfruJg7XN3YJLEPelom62wvzhvLXJFLQZlQCDrMx+PC
|
||||||
|
ofWs4IA7jR8JaXZjIGdkEU0GgRPy8zKPUe3dUBHi2UR4eKT4cRCn4IwCrFx4BQjV
|
||||||
|
AxNKNDGpe+fTVOzII/UX+FppDdGZZ4g0y3E1mQUEKkff4dKCK7vhlGJR9D+5v/V0
|
||||||
|
/stwP72aXczijuVtnXXyli+oj24NaijoqQluNCD3MvV/INovLL2Tyk54H3/GvpU1
|
||||||
|
+sJbpE2+UPh+Rh8DNkT6RPRguymJO8MSsdLt/qvVD8BlZ7I9V3XZlDKosCRTUyxf
|
||||||
|
jjFpa+VzB3nt7uFtIXZ9HNGhQIpOULvkFGizWV+tS8PpGdTFVzDjyWg0HUKWn8g8
|
||||||
|
IiWR9S40h6mHjVuTuxA9tlO69PuTjGK7MlAvFTDaPC8seau1LUiqtQ+prnSLI0h1
|
||||||
|
6GfI9W2G7BKKVPloErODhLcsOcwRcmaJVW+yBda3te8+cMBIvtQYKAYSCtg8qXws
|
||||||
|
xyfPLo4GChbGGRbRCuM3mB1lG1qHEivJ0vynsgolp0t8jaXSFVBVgYj+C6Vd9/hl
|
||||||
|
ieUcOwIDAQABoDUwMwYJKoZIhvcNAQkOMSYwJDAiBgNVHREEGzAZhwR/AAABgRF2
|
||||||
|
YWxpZEBleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAe1u3wYMMKaZ3d5Wz
|
||||||
|
jKH971CF3sl+KYl+oV0ekD8dbYe+szERgajn6Y5IYVxxi5o9UgeAWqnyHCiqsW8T
|
||||||
|
MQdUwMa67Ym/pHKSVoBlGePAKHqock0+iSsVBMcPpU9RkxdSW2aVtdb0DGfyB952
|
||||||
|
t3dSb0LaITu30fe8p7lxrL0DKESbwd4N2XQE1F5Vf+1OodvpJinn4Wqzn45hqRf0
|
||||||
|
imxrCgVjT5VtR+NRzKCK3Msmh+cJGpR3zgXwGKqgHLWzhvSoQwRWYE3apMK5xLk7
|
||||||
|
N1sWVxEKK5+L/CDaMNGQFx5lPiCN3bUudCq4uSZcPLO5AuDpSeLKnknBrWA6HcbB
|
||||||
|
WvnwtKmHeVe2qogPViKGuwE16rnPlp9hysPl2ckmtqEsXRagIAh5fMI3OoRbZmVV
|
||||||
|
jfJm21U4YkUWuMKet3EU1StT6T8T6O7QEFA4w4s5+m3dsjDZ9iTuK9/dCs1xnIke
|
||||||
|
4uJYmh3YrNl8IjMffJuWxA+/de3JO1UljC2EAFxa5KAc24+qyeWwky4tMv72gTOp
|
||||||
|
6q3k2wnsrK5B1errRV37OLgxtoh1I3Rgp+0B77SOK/PpD/JJazJG5O9bBJOvHJc0
|
||||||
|
STW9Td2CzgC2lKGfvkX6UYgVy/9HDq7/EKXP/G2f3kRik2NPUhGcnAH9nyL9SvpP
|
||||||
|
+T4CZ+FumDj5DulARk6arSq+uy4=
|
||||||
|
-----END CERTIFICATE REQUEST-----
|
|
@ -0,0 +1,23 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIID1TCCAr2gAwIBAgIJAJIiPq+77hevMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV
|
||||||
|
BAMTC2V4YW1wbGUuY29tMB4XDTE4MDQyNjEyMjE1MloXDTE5MDQyNjEyMjE1Mlow
|
||||||
|
FjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
|
||||||
|
ggIKAoICAQDO7stcdJQwUtVeJriwpAswDAirO827peSlgdxsfW8X9M2hE9ihvESE
|
||||||
|
ILb7TRMRiFlDyQYg1BxKMrJ0DZmixFi8RvUCZbH6TFOUMsk+w1FhpzjuqAqxNQ51
|
||||||
|
s7u30sfruJg7XN3YJLEPelom62wvzhvLXJFLQZlQCDrMx+PCofWs4IA7jR8JaXZj
|
||||||
|
IGdkEU0GgRPy8zKPUe3dUBHi2UR4eKT4cRCn4IwCrFx4BQjVAxNKNDGpe+fTVOzI
|
||||||
|
I/UX+FppDdGZZ4g0y3E1mQUEKkff4dKCK7vhlGJR9D+5v/V0/stwP72aXczijuVt
|
||||||
|
nXXyli+oj24NaijoqQluNCD3MvV/INovLL2Tyk54H3/GvpU1+sJbpE2+UPh+Rh8D
|
||||||
|
NkT6RPRguymJO8MSsdLt/qvVD8BlZ7I9V3XZlDKosCRTUyxfjjFpa+VzB3nt7uFt
|
||||||
|
IXZ9HNGhQIpOULvkFGizWV+tS8PpGdTFVzDjyWg0HUKWn8g8IiWR9S40h6mHjVuT
|
||||||
|
uxA9tlO69PuTjGK7MlAvFTDaPC8seau1LUiqtQ+prnSLI0h16GfI9W2G7BKKVPlo
|
||||||
|
ErODhLcsOcwRcmaJVW+yBda3te8+cMBIvtQYKAYSCtg8qXwsxyfPLo4GChbGGRbR
|
||||||
|
CuM3mB1lG1qHEivJ0vynsgolp0t8jaXSFVBVgYj+C6Vd9/hlieUcOwIDAQABoyYw
|
||||||
|
JDAiBgNVHREEGzAZhwR/AAABgRF2YWxpZEBleGFtcGxlLmNvbTANBgkqhkiG9w0B
|
||||||
|
AQUFAAOCAQEAp2T99t93hxPyCDaqfTF0lsdzIgxZ5GkSzYTYQ2pekLfMDUUy4WFQ
|
||||||
|
AppdnSJSpm6b+xWO2DkO8UAgOdSEORf/Qpfm+UpHaEYZlQiWQ0zNmIQgBoh6indU
|
||||||
|
bEZKeL6aAOfIshPNfmqjFt+DpEClrQvCHJggG/rB77Ujj6hPY2+8h4JjbjeX7Pe9
|
||||||
|
oUEx9LpZ5Qpo6PK5vB537PP7Q2qp2PIr29DLz1VeLCbqUnV+j7qT0T3hhqurnpTA
|
||||||
|
QUiRZI0etgeP/B5lw/S4AWijq+R6RasdPAS4UNHsYK+PSGiqdhW/bJvSx5UBXQbk
|
||||||
|
DuY2A4kdv60H5Aw45/F6enH2Fg1kg7PlQA==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,52 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDO7stcdJQwUtVe
|
||||||
|
JriwpAswDAirO827peSlgdxsfW8X9M2hE9ihvESEILb7TRMRiFlDyQYg1BxKMrJ0
|
||||||
|
DZmixFi8RvUCZbH6TFOUMsk+w1FhpzjuqAqxNQ51s7u30sfruJg7XN3YJLEPelom
|
||||||
|
62wvzhvLXJFLQZlQCDrMx+PCofWs4IA7jR8JaXZjIGdkEU0GgRPy8zKPUe3dUBHi
|
||||||
|
2UR4eKT4cRCn4IwCrFx4BQjVAxNKNDGpe+fTVOzII/UX+FppDdGZZ4g0y3E1mQUE
|
||||||
|
Kkff4dKCK7vhlGJR9D+5v/V0/stwP72aXczijuVtnXXyli+oj24NaijoqQluNCD3
|
||||||
|
MvV/INovLL2Tyk54H3/GvpU1+sJbpE2+UPh+Rh8DNkT6RPRguymJO8MSsdLt/qvV
|
||||||
|
D8BlZ7I9V3XZlDKosCRTUyxfjjFpa+VzB3nt7uFtIXZ9HNGhQIpOULvkFGizWV+t
|
||||||
|
S8PpGdTFVzDjyWg0HUKWn8g8IiWR9S40h6mHjVuTuxA9tlO69PuTjGK7MlAvFTDa
|
||||||
|
PC8seau1LUiqtQ+prnSLI0h16GfI9W2G7BKKVPloErODhLcsOcwRcmaJVW+yBda3
|
||||||
|
te8+cMBIvtQYKAYSCtg8qXwsxyfPLo4GChbGGRbRCuM3mB1lG1qHEivJ0vynsgol
|
||||||
|
p0t8jaXSFVBVgYj+C6Vd9/hlieUcOwIDAQABAoICAQDFitqh6TxqITlFBwv6vK9d
|
||||||
|
b696371XrFdo1F57RwcdxHnkklCUnWh/BcgIgJx6eUJV3nq2LibPgjQva6hF5NCc
|
||||||
|
89QDNNfBjMmgyRaqjsSKx5sm4U5Lus2R+UFzi4mEcpUI3m99XhGVKAUV8Fo4DLcl
|
||||||
|
3LlrMTVNXH3dbdj0va4NGcfwkZiWYJI+sPliYs24LtK/dADJJro/MqfQef7OTsWV
|
||||||
|
0kHHMSoXhzlC7fNvfd8VUFw0Ym99pC3iJclc155feWyk2FwDok7xjqFmR4KTrD1M
|
||||||
|
PLm/7+ooOFX5WdHVnULSZlb3HSJxCV7l1JJ7QXo/nKS/s59X875n8OWjdoc7lD4T
|
||||||
|
Xw/K9CzJCyhJ/HDhTAea1+MNTig4a6wjdSim6vasig/Gkot6jjS2lhnZae8ZhYxP
|
||||||
|
GUx4JcPthHppgHt8s6Jb2PHuqNVRmVB0x41c5mmXOnJcSqOX0XhbSbeS1TUV8BiC
|
||||||
|
HMaa+agt7RpQOb5uxpb+Hath/88tsjDXI0ZHNAG43ndkHxSQQ9P/q/m5uaLwuJyo
|
||||||
|
Yb06yUy/g7ceXpJFjGsjO+33DmamvligqOswgg+oazMFo8S9ZUJw6sSXhM/XiHla
|
||||||
|
JOj+Vatfj0ViVcaGlO2kWughuCT5thn92bgC9V2VnJhbaSzSaQlRphlbuSYJEYj0
|
||||||
|
S1uIbwPzTrcBQuekwY50YQKCAQEA/vve5K/nAnw4KLSrKwwCp9trYSm8C5czv2jV
|
||||||
|
tn6vQtckQMrw/hubX7TcTTgTuGboGdHMwZMFJBKpx6AlRHCR5IBw8fR1z+58c+2V
|
||||||
|
VJgllc23eKwCcBMKoe6LmsiUXOWmc7MuHc+qQS+9OemO93nNafsSwFCkucBFQs/3
|
||||||
|
Yx7J3zNvMOuy+dq3jrxO0xl2jBF0pcmJF/czrvbMCD7tvDntgqvpAnybgrwm2cu3
|
||||||
|
Q5F6i+E5w6VDhCprQL/aK95iT7cPmfdGxsUCdfNzDGIJFHZp2Hrar1TsOP6ESsDl
|
||||||
|
Q/Oz9oO1vMy7MymJjWFoVELBlCBxDEgubyM1f8cE1tQ6UAqFSwKCAQEAz8HnKWPe
|
||||||
|
NWZtqdAzSmY+3ZxSe1BbukOo4XtCV8LfRHGazKpXMTqsO9l7ynK7ifXv3b3GHTr+
|
||||||
|
ck2Af/vyiVx6f7Ty2dmBotFQDzg0HfKD2skAPyH8cHpA8TUeL3yMOR3XQU5/pOnG
|
||||||
|
tn84n7KWpAyZXh8gzMnmzWjMlb9pUlkKcATUj0gb8iSa9PV0zBwMKYKY0ngznJT2
|
||||||
|
CgE1vhy59rpuUVMrQ8i5iW9jbqYVrqID+ta2DWgcLsEXft7jKfupnRHF0Dvc650p
|
||||||
|
+Lkxv0YgKjUg5sYc2QJbIiBxXaW0cTRrw/KfOe4kvdG5RMF60Six+W1DIW2l+qi3
|
||||||
|
irnDRvRm1N6e0QKCAQEA86d5MaxJIl3TSEqEeikK7J3GuV0pHSZKQ7EI70+VaFiv
|
||||||
|
gt6qdReqXEU2cu+QIJjtV6bcc2lq8zKGXITSt9ieAO0fgIWqgpyQ/jJcjS6qU8D1
|
||||||
|
fnFYDwKTGXQaoTjkVPT6HvtsqP4E4i+dMZbWj/MrcAeEvpMRJZLuXE7gRi5ol0nO
|
||||||
|
CcBhEVKILvQQmrZtSqFvhvDTeTw2fg3FoGeJw2DTbheaHE84RzBGK774C7Abm0kI
|
||||||
|
asUkhEoInSH3eA4UgbobRXQ+hLhDhrSxDncr2ArjUALtr7eF11yWy9wR+OIK6Rio
|
||||||
|
9JXqmJQrphcbm9ECq+poPGVJQdgySjzCigrZAh1biwKCAQBiBnFVXCOaOov/lZa9
|
||||||
|
weRjl8BrIo1FI2tpiEjTM8U4fAm4C588QRzG2GTKLrxB6eKVU1dIr28i62J4AJ59
|
||||||
|
JT8/RldXZoL+GZiWtcQRZT3FWxVctGJxh51gsdleOnvG70eDLtCXNR5nOTu0TgU5
|
||||||
|
viAXAsTtG05lGM9+0GOXUR/VntHUEQfuhkr+zVmgfJNYeqA0njZr6PT134BGBTPR
|
||||||
|
MEGg6Yb+YpT4PbBCouaUESmjju8zAC5b+Qtm9y9jvbRXwez9xWEFYpBNJMROJX5D
|
||||||
|
q/GsMUmnMq9hOMGEmAy9ZSh7udxa7vwy++NYh5m1Wmgu8di8ywmHbVe8gs2aivKB
|
||||||
|
+dAhAoIBAQC7nSuRSmRGeKJCAqikMFPVdFdLaTnEw4i/fcyYsPa+o2hTWXyLll8K
|
||||||
|
lwSnBxe+BCvdeQ8cWzg3rPaIBVzUjDecZjdwjcHnhlHvgHjEvFX339rvpD7J2HIb
|
||||||
|
DaVqvtPniCFdNK4Jyvd3JMtNq34SIHFAcmB9358JuKsOwCmk8CpMAqKPVsKj7m6H
|
||||||
|
ETISh/K8aI2vZxVZ4WN4FsQTCqmtQDXFSGpZF5EZSpMJIB3ZZLt2jyyDW2DaZ+1T
|
||||||
|
yuVl9jU56fTtacQROQY7cvrwznX0lFpmniwl0Aj0wln/svFAqKo1+RujqApw5iYn
|
||||||
|
ssH1dH2tESx6RpMMyLYihjHVDC/ULUVu
|
||||||
|
-----END PRIVATE KEY-----
|
|
@ -10,12 +10,7 @@ distinguished_name = dn
|
||||||
CN = example.com
|
CN = example.com
|
||||||
|
|
||||||
[ req_v3 ]
|
[ req_v3 ]
|
||||||
subjectAltName = @alt_names
|
|
||||||
2.1.1.1=ASN1:UTF8String:A UTF8String Extension
|
2.1.1.1=ASN1:UTF8String:A UTF8String Extension
|
||||||
2.1.1.2=ASN1:UTF8:A UTF8 Extension
|
2.1.1.2=ASN1:UTF8:A UTF8 Extension
|
||||||
2.1.1.3=ASN1:IA5:An IA5 Extension
|
2.1.1.3=ASN1:IA5:An IA5 Extension
|
||||||
2.1.1.4=ASN1:VISIBLE:A Visible Extension
|
2.1.1.4=ASN1:VISIBLE:A Visible Extension
|
||||||
|
|
||||||
[ alt_names ]
|
|
||||||
DNS.1 = example.com
|
|
||||||
IP.1 = 127.0.0.1
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
[ req ]
|
||||||
|
default_bits = 2048
|
||||||
|
encrypt_key = no
|
||||||
|
prompt = no
|
||||||
|
default_md = sha256
|
||||||
|
req_extensions = req_v3
|
||||||
|
distinguished_name = dn
|
||||||
|
|
||||||
|
[ dn ]
|
||||||
|
CN = example.com
|
||||||
|
|
||||||
|
[ req_v3 ]
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
|
||||||
|
[ alt_names ]
|
||||||
|
DNS.1 = example.com
|
||||||
|
IP.1 = 127.0.0.1
|
||||||
|
URI.1 = spiffe://example.com/host
|
|
@ -0,0 +1,17 @@
|
||||||
|
-----BEGIN CERTIFICATE REQUEST-----
|
||||||
|
MIICpTCCAY0CAQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3
|
||||||
|
DQEBAQUAA4IBDwAwggEKAoIBAQDEtoz6THzA8RFNJ+wu40Pa30Inyprv3xRGYA71
|
||||||
|
0T3yLrWUA0xaS8i7HHXDaEVmtHi7I+dFRqGwCgtDLY3sXN1C1t/U6V6xhhQ1hRW7
|
||||||
|
PJhbGfsfi8uBx83amWiSMlmEBYPryQzPS+8mmRErBi6EdmgbdGWV5IcovMddDxE1
|
||||||
|
Npc1vwmTxDUOe6mRSa8UkaR9nwFl8LTz9clIkGlOJLHWD2oX15PVr7SKYco+MrIh
|
||||||
|
HLKkYMgATFJ05EKLyRxO/lQWD6ibUYJuGhFeNyjk34swl3uoWQBGndxcs2BQP4OL
|
||||||
|
EfnsoXVDrHwjZ1FWSu/Bf6TfKvwo5It1IZLnm+cCTqxCnaLRAgMBAAGgSjBIBgkq
|
||||||
|
hkiG9w0BCQ4xOzA5MDcGA1UdEQQwMC6CC2V4YW1wbGUuY29thwR/AAABhhlzcGlm
|
||||||
|
ZmU6Ly9leGFtcGxlLmNvbS9ob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQBw2y7bPrLk
|
||||||
|
B7DrZRvO/s8yj/Mi2iS/q3KEACEUxHTXH9GrqnQJ1n00WjaEu5JgXW8F08738nj/
|
||||||
|
QhO5IM9ZMBtFyt9/GguZzGWnGUGUvtfM/ps/qzF6lAnjxYnFfqJeDWhg4SQsW6ZW
|
||||||
|
eFZ3S1kx0iQjy+Y7oWZNObbgDhszdJa6swN1WJBB8BZuiDJYXMBzfWdR6aZStJ0Z
|
||||||
|
lUHyaQbILXRc+meuDY7KeILJhldlE8oU/NENO1w1WXcsseXg8790pPYg+uR/uXg0
|
||||||
|
0iWPtqgjO+55eAvkZ5nY0N/kABV1oaCB8bVs6/2HPqquPX6c+xkcUI/HY8SJgWzk
|
||||||
|
AHCG7VIB4W94
|
||||||
|
-----END CERTIFICATE REQUEST-----
|
|
@ -0,0 +1,18 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC6jCCAdKgAwIBAgIJAJIiPq+77hekMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV
|
||||||
|
BAMTC2V4YW1wbGUuY29tMB4XDTE4MDMzMTE2MTE0NVoXDTE5MDMzMTE2MTE0NVow
|
||||||
|
FjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||||
|
ggEKAoIBAQDEtoz6THzA8RFNJ+wu40Pa30Inyprv3xRGYA710T3yLrWUA0xaS8i7
|
||||||
|
HHXDaEVmtHi7I+dFRqGwCgtDLY3sXN1C1t/U6V6xhhQ1hRW7PJhbGfsfi8uBx83a
|
||||||
|
mWiSMlmEBYPryQzPS+8mmRErBi6EdmgbdGWV5IcovMddDxE1Npc1vwmTxDUOe6mR
|
||||||
|
Sa8UkaR9nwFl8LTz9clIkGlOJLHWD2oX15PVr7SKYco+MrIhHLKkYMgATFJ05EKL
|
||||||
|
yRxO/lQWD6ibUYJuGhFeNyjk34swl3uoWQBGndxcs2BQP4OLEfnsoXVDrHwjZ1FW
|
||||||
|
Su/Bf6TfKvwo5It1IZLnm+cCTqxCnaLRAgMBAAGjOzA5MDcGA1UdEQQwMC6CC2V4
|
||||||
|
YW1wbGUuY29thwR/AAABhhlzcGlmZmU6Ly9leGFtcGxlLmNvbS9ob3N0MA0GCSqG
|
||||||
|
SIb3DQEBBQUAA4IBAQDhR59hSpL4k4wbK3bA17YoNwFBsDpDcoU2iB9NDUTj+j+T
|
||||||
|
Rgumt+VHtgxuGRDFPQ+0D2hmJJHNCHKulgeDKVLtY/c5dCEsk8epLQwoCd/pQsNR
|
||||||
|
Lj102g83rCrU0pfTFjAUoecmHBFt7GDxVyWDsJgGItMatPQuWyZXTzO8JdhCfpMP
|
||||||
|
m7z65VYZjIPgevpSR5NVJDU8u2jRCkRQBFqOXotJS6EObu4P8aly4YhwiMf1B0L8
|
||||||
|
60XHbBksOQSZOky37uFhaab78bAu5nd2kN1K4qSObTJshCZAwRYk0XdCjDrMcZRJ
|
||||||
|
Fp+yygib+K8e7o71Co0zUdSU0yxOKGsWvjz1BUVl
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDEtoz6THzA8RFN
|
||||||
|
J+wu40Pa30Inyprv3xRGYA710T3yLrWUA0xaS8i7HHXDaEVmtHi7I+dFRqGwCgtD
|
||||||
|
LY3sXN1C1t/U6V6xhhQ1hRW7PJhbGfsfi8uBx83amWiSMlmEBYPryQzPS+8mmREr
|
||||||
|
Bi6EdmgbdGWV5IcovMddDxE1Npc1vwmTxDUOe6mRSa8UkaR9nwFl8LTz9clIkGlO
|
||||||
|
JLHWD2oX15PVr7SKYco+MrIhHLKkYMgATFJ05EKLyRxO/lQWD6ibUYJuGhFeNyjk
|
||||||
|
34swl3uoWQBGndxcs2BQP4OLEfnsoXVDrHwjZ1FWSu/Bf6TfKvwo5It1IZLnm+cC
|
||||||
|
TqxCnaLRAgMBAAECggEAYLdYbR/6HmroFMVSLGN000H9ps7IirNlpoxIDrhH+rDY
|
||||||
|
eeN9QNAN62E8zUyRAsQsr+YhKUBm8sSdcPQO2W13JAu9lVMAScwgV4gNfTd3uSL3
|
||||||
|
AzWaYz63iYjvjyHOPUjw6Za6A5nUBWgwtrSdXmdRHF6IK8Bma7MVWj20OjOS+MsM
|
||||||
|
ScXk+yMTzpQYZ+AhP6rgcccn6djtk+Mqrpa7yW5cTDkQ0+/MF0KR7tYUbakRSimI
|
||||||
|
Ph6e+zFt4infOWP5fDr0oSpMXA2chh0INTtxbltnJzvaaPF8LSzyihWTZszABc84
|
||||||
|
Ckgrvmt5DViYbmfKHk0csS/xF/wdygfkkJHML8l/IQKBgQD9CMaDgfpM78uH8Kgm
|
||||||
|
Ja/ANu4Te5zO/n5E96PHdvCN+m7pCMgYuXuKgXDADgD1O6MItzDnEpkubluffARf
|
||||||
|
1eJyw9ner0tTAs8bZgtKdLQvaghq5Afk1+m8XDTskJsVLVGrozvJLuabPqnZrkRH
|
||||||
|
AxLdZjiAh6z2csFVYTQnMQSfhQKBgQDHBMjapcDx9y/jUq/yoFvwkdT3THQO9JgK
|
||||||
|
XC5NOHGVhyT3695wpqi/ANA4b8P9MmAzcUkT8a3jcqV87OIQmK3Y1oGvjHQCKS60
|
||||||
|
OYE9TadpxwW2uzxS5T7YegXf5L3uHinoWHlLklN+Q9pvJStw4QrDzhd8rtcZA+FN
|
||||||
|
KBmjzYdJ3QKBgQDYutl97qi7mXEVgPYlpoYA94u4OFq5mZYB8LLhuGiW03iINbNe
|
||||||
|
KhE9M12lwtjjNC+S2YYThgSaln/3/LuqcoLBlitY54B3G6LVbvQg1BE5w3JuS97P
|
||||||
|
Dnjvk3LpZXrQCr83altdGMUBGA1XnEJzKJjR9ipTPOLTPLuIK/gF0aCKGQKBgQCm
|
||||||
|
ZFitfZGge4M9Mt/KIcpciwCcNf5+ln8bglBv3XYRhykgYsLaOmyxLLPpy3/4DAsk
|
||||||
|
V1263//7PtofZUnoiE4pEcbhh7NiLx5OLhngsDD9Hhmn2kkoIWR2xyZsN6mYEP4G
|
||||||
|
tRnMVi2aTo6tCE2WlYBTjtZSNze9QWI4CQPO0MKAvQKBgQCzpJAJXl04zQv9S5uW
|
||||||
|
pH3xShmd0Zjv9tNyOVNqWUeg47IFzNC2w/6FqYkhd9C4DCAibzPx7WkVjYAR+ivY
|
||||||
|
NQv1usVhV3maJX5rw+C4Zck8kAmiqMbLacUVdy/5E2Mbk7xqjAvu+qrMFdSk/2GR
|
||||||
|
raR1xOEvE0cKWIwr8c8wIva4wA==
|
||||||
|
-----END PRIVATE KEY-----
|
|
@ -2,16 +2,9 @@ package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/x509"
|
|
||||||
"encoding/pem"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
|
||||||
"github.com/hashicorp/vault/helper/consts"
|
"github.com/hashicorp/vault/helper/consts"
|
||||||
"github.com/hashicorp/vault/helper/ldaputil"
|
"github.com/hashicorp/vault/helper/ldaputil"
|
||||||
"github.com/hashicorp/vault/helper/tlsutil"
|
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/framework"
|
"github.com/hashicorp/vault/logical/framework"
|
||||||
)
|
)
|
||||||
|
@ -19,105 +12,7 @@ import (
|
||||||
func pathConfig(b *backend) *framework.Path {
|
func pathConfig(b *backend) *framework.Path {
|
||||||
return &framework.Path{
|
return &framework.Path{
|
||||||
Pattern: `config`,
|
Pattern: `config`,
|
||||||
Fields: map[string]*framework.FieldSchema{
|
Fields: ldaputil.ConfigFields(),
|
||||||
"url": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Default: "ldap://127.0.0.1",
|
|
||||||
Description: "LDAP URL to connect to (default: ldap://127.0.0.1). Multiple URLs can be specified by concatenating them with commas; they will be tried in-order.",
|
|
||||||
},
|
|
||||||
|
|
||||||
"userdn": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Description: "LDAP domain to use for users (eg: ou=People,dc=example,dc=org)",
|
|
||||||
},
|
|
||||||
|
|
||||||
"binddn": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Description: "LDAP DN for searching for the user DN (optional)",
|
|
||||||
},
|
|
||||||
|
|
||||||
"bindpass": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Description: "LDAP password for searching for the user DN (optional)",
|
|
||||||
},
|
|
||||||
|
|
||||||
"groupdn": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Description: "LDAP search base to use for group membership search (eg: ou=Groups,dc=example,dc=org)",
|
|
||||||
},
|
|
||||||
|
|
||||||
"groupfilter": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Default: "(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))",
|
|
||||||
Description: `Go template for querying group membership of user (optional)
|
|
||||||
The template can access the following context variables: UserDN, Username
|
|
||||||
Example: (&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))
|
|
||||||
Default: (|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))`,
|
|
||||||
},
|
|
||||||
|
|
||||||
"groupattr": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Default: "cn",
|
|
||||||
Description: `LDAP attribute to follow on objects returned by <groupfilter>
|
|
||||||
in order to enumerate user group membership.
|
|
||||||
Examples: "cn" or "memberOf", etc.
|
|
||||||
Default: cn`,
|
|
||||||
},
|
|
||||||
|
|
||||||
"upndomain": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Description: "Enables userPrincipalDomain login with [username]@UPNDomain (optional)",
|
|
||||||
},
|
|
||||||
|
|
||||||
"userattr": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Default: "cn",
|
|
||||||
Description: "Attribute used for users (default: cn)",
|
|
||||||
},
|
|
||||||
|
|
||||||
"certificate": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Description: "CA certificate to use when verifying LDAP server certificate, must be x509 PEM encoded (optional)",
|
|
||||||
},
|
|
||||||
|
|
||||||
"discoverdn": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeBool,
|
|
||||||
Description: "Use anonymous bind to discover the bind DN of a user (optional)",
|
|
||||||
},
|
|
||||||
|
|
||||||
"insecure_tls": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeBool,
|
|
||||||
Description: "Skip LDAP server SSL Certificate verification - VERY insecure (optional)",
|
|
||||||
},
|
|
||||||
|
|
||||||
"starttls": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeBool,
|
|
||||||
Description: "Issue a StartTLS command after establishing unencrypted connection (optional)",
|
|
||||||
},
|
|
||||||
|
|
||||||
"tls_min_version": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Default: "tls12",
|
|
||||||
Description: "Minimum TLS version to use. Accepted values are 'tls10', 'tls11' or 'tls12'. Defaults to 'tls12'",
|
|
||||||
},
|
|
||||||
|
|
||||||
"tls_max_version": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Default: "tls12",
|
|
||||||
Description: "Maximum TLS version to use. Accepted values are 'tls10', 'tls11' or 'tls12'. Defaults to 'tls12'",
|
|
||||||
},
|
|
||||||
|
|
||||||
"deny_null_bind": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeBool,
|
|
||||||
Default: true,
|
|
||||||
Description: "Denies an unauthenticated LDAP bind request if the user's password is empty; defaults to true",
|
|
||||||
},
|
|
||||||
|
|
||||||
"case_sensitive_names": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeBool,
|
|
||||||
Description: "If true, case sensitivity will be used when comparing usernames and groups for matching policies.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||||
logical.ReadOperation: b.pathConfigRead,
|
logical.ReadOperation: b.pathConfigRead,
|
||||||
|
@ -140,7 +35,7 @@ func (b *backend) Config(ctx context.Context, req *logical.Request) (*ldaputil.C
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new ConfigEntry, filling in defaults where appropriate
|
// Create a new ConfigEntry, filling in defaults where appropriate
|
||||||
result, err := b.newConfigEntry(fd)
|
result, err := ldaputil.NewConfigEntry(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -195,147 +90,14 @@ func (b *backend) pathConfigRead(ctx context.Context, req *logical.Request, d *f
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := &logical.Response{
|
resp := &logical.Response{
|
||||||
Data: map[string]interface{}{
|
Data: cfg.PasswordlessMap(),
|
||||||
"url": cfg.Url,
|
|
||||||
"userdn": cfg.UserDN,
|
|
||||||
"groupdn": cfg.GroupDN,
|
|
||||||
"groupfilter": cfg.GroupFilter,
|
|
||||||
"groupattr": cfg.GroupAttr,
|
|
||||||
"upndomain": cfg.UPNDomain,
|
|
||||||
"userattr": cfg.UserAttr,
|
|
||||||
"certificate": cfg.Certificate,
|
|
||||||
"insecure_tls": cfg.InsecureTLS,
|
|
||||||
"starttls": cfg.StartTLS,
|
|
||||||
"binddn": cfg.BindDN,
|
|
||||||
"deny_null_bind": cfg.DenyNullBind,
|
|
||||||
"discoverdn": cfg.DiscoverDN,
|
|
||||||
"tls_min_version": cfg.TLSMinVersion,
|
|
||||||
"tls_max_version": cfg.TLSMaxVersion,
|
|
||||||
"case_sensitive_names": *cfg.CaseSensitiveNames,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Creates and initializes a ConfigEntry object with its default values,
|
|
||||||
* as specified by the passed schema.
|
|
||||||
*/
|
|
||||||
func (b *backend) newConfigEntry(d *framework.FieldData) (*ldaputil.ConfigEntry, error) {
|
|
||||||
cfg := new(ldaputil.ConfigEntry)
|
|
||||||
|
|
||||||
url := d.Get("url").(string)
|
|
||||||
if url != "" {
|
|
||||||
cfg.Url = strings.ToLower(url)
|
|
||||||
}
|
|
||||||
userattr := d.Get("userattr").(string)
|
|
||||||
if userattr != "" {
|
|
||||||
cfg.UserAttr = strings.ToLower(userattr)
|
|
||||||
}
|
|
||||||
userdn := d.Get("userdn").(string)
|
|
||||||
if userdn != "" {
|
|
||||||
cfg.UserDN = userdn
|
|
||||||
}
|
|
||||||
groupdn := d.Get("groupdn").(string)
|
|
||||||
if groupdn != "" {
|
|
||||||
cfg.GroupDN = groupdn
|
|
||||||
}
|
|
||||||
groupfilter := d.Get("groupfilter").(string)
|
|
||||||
if groupfilter != "" {
|
|
||||||
// Validate the template before proceeding
|
|
||||||
_, err := template.New("queryTemplate").Parse(groupfilter)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errwrap.Wrapf("invalid groupfilter: {{err}}", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.GroupFilter = groupfilter
|
|
||||||
}
|
|
||||||
groupattr := d.Get("groupattr").(string)
|
|
||||||
if groupattr != "" {
|
|
||||||
cfg.GroupAttr = groupattr
|
|
||||||
}
|
|
||||||
upndomain := d.Get("upndomain").(string)
|
|
||||||
if upndomain != "" {
|
|
||||||
cfg.UPNDomain = upndomain
|
|
||||||
}
|
|
||||||
certificate := d.Get("certificate").(string)
|
|
||||||
if certificate != "" {
|
|
||||||
block, _ := pem.Decode([]byte(certificate))
|
|
||||||
|
|
||||||
if block == nil || block.Type != "CERTIFICATE" {
|
|
||||||
return nil, fmt.Errorf("failed to decode PEM block in the certificate")
|
|
||||||
}
|
|
||||||
_, err := x509.ParseCertificate(block.Bytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errwrap.Wrapf("failed to parse certificate: {{err}}", err)
|
|
||||||
}
|
|
||||||
cfg.Certificate = certificate
|
|
||||||
}
|
|
||||||
insecureTLS := d.Get("insecure_tls").(bool)
|
|
||||||
if insecureTLS {
|
|
||||||
cfg.InsecureTLS = insecureTLS
|
|
||||||
}
|
|
||||||
cfg.TLSMinVersion = d.Get("tls_min_version").(string)
|
|
||||||
if cfg.TLSMinVersion == "" {
|
|
||||||
return nil, fmt.Errorf("failed to get 'tls_min_version' value")
|
|
||||||
}
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
_, ok = tlsutil.TLSLookup[cfg.TLSMinVersion]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("invalid 'tls_min_version'")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.TLSMaxVersion = d.Get("tls_max_version").(string)
|
|
||||||
if cfg.TLSMaxVersion == "" {
|
|
||||||
return nil, fmt.Errorf("failed to get 'tls_max_version' value")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, ok = tlsutil.TLSLookup[cfg.TLSMaxVersion]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("invalid 'tls_max_version'")
|
|
||||||
}
|
|
||||||
if cfg.TLSMaxVersion < cfg.TLSMinVersion {
|
|
||||||
return nil, fmt.Errorf("'tls_max_version' must be greater than or equal to 'tls_min_version'")
|
|
||||||
}
|
|
||||||
|
|
||||||
startTLS := d.Get("starttls").(bool)
|
|
||||||
if startTLS {
|
|
||||||
cfg.StartTLS = startTLS
|
|
||||||
}
|
|
||||||
|
|
||||||
bindDN := d.Get("binddn").(string)
|
|
||||||
if bindDN != "" {
|
|
||||||
cfg.BindDN = bindDN
|
|
||||||
}
|
|
||||||
|
|
||||||
bindPass := d.Get("bindpass").(string)
|
|
||||||
if bindPass != "" {
|
|
||||||
cfg.BindPassword = bindPass
|
|
||||||
}
|
|
||||||
|
|
||||||
denyNullBind := d.Get("deny_null_bind").(bool)
|
|
||||||
if denyNullBind {
|
|
||||||
cfg.DenyNullBind = denyNullBind
|
|
||||||
}
|
|
||||||
|
|
||||||
discoverDN := d.Get("discoverdn").(bool)
|
|
||||||
if discoverDN {
|
|
||||||
cfg.DiscoverDN = discoverDN
|
|
||||||
}
|
|
||||||
|
|
||||||
caseSensitiveNames, ok := d.GetOk("case_sensitive_names")
|
|
||||||
if ok {
|
|
||||||
cfg.CaseSensitiveNames = new(bool)
|
|
||||||
*cfg.CaseSensitiveNames = caseSensitiveNames.(bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
return cfg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
// Build a ConfigEntry struct out of the supplied FieldData
|
// Build a ConfigEntry struct out of the supplied FieldData
|
||||||
cfg, err := b.newConfigEntry(d)
|
cfg, err := ldaputil.NewConfigEntry(d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logical.ErrorResponse(err.Error()), nil
|
return logical.ErrorResponse(err.Error()), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,10 +66,12 @@ func (c *AuthCommand) Run(args []string) int {
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(arg, "-methods"):
|
case strings.HasPrefix(arg, "-methods"):
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"WARNING! The -methods flag is deprecated. Please use "+
|
"WARNING! The -methods flag is deprecated. Please use "+
|
||||||
"\"vault auth list\" instead. This flag will be removed in "+
|
"\"vault auth list\" instead. This flag will be removed in "+
|
||||||
"Vault 0.11 (or later).") + "\n")
|
"Vault 0.11 (or later).") + "\n")
|
||||||
|
}
|
||||||
return (&AuthListCommand{
|
return (&AuthListCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: &BaseCommand{
|
||||||
UI: c.UI,
|
UI: c.UI,
|
||||||
|
@ -77,10 +79,12 @@ func (c *AuthCommand) Run(args []string) int {
|
||||||
},
|
},
|
||||||
}).Run(nil)
|
}).Run(nil)
|
||||||
case strings.HasPrefix(arg, "-method-help"):
|
case strings.HasPrefix(arg, "-method-help"):
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"WARNING! The -method-help flag is deprecated. Please use "+
|
"WARNING! The -method-help flag is deprecated. Please use "+
|
||||||
"\"vault auth help\" instead. This flag will be removed in "+
|
"\"vault auth help\" instead. This flag will be removed in "+
|
||||||
"Vault 0.11 (or later).") + "\n")
|
"Vault 0.11 (or later).") + "\n")
|
||||||
|
}
|
||||||
// Parse the args to pull out the method, suppressing any errors because
|
// Parse the args to pull out the method, suppressing any errors because
|
||||||
// there could be other flags that we don't care about.
|
// there could be other flags that we don't care about.
|
||||||
f := flag.NewFlagSet("", flag.ContinueOnError)
|
f := flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
@ -101,11 +105,13 @@ func (c *AuthCommand) Run(args []string) int {
|
||||||
|
|
||||||
// If we got this far, we have an arg or a series of args that should be
|
// If we got this far, we have an arg or a series of args that should be
|
||||||
// passed directly to the new "vault login" command.
|
// passed directly to the new "vault login" command.
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"WARNING! The \"vault auth ARG\" command is deprecated and is now a "+
|
"WARNING! The \"vault auth ARG\" command is deprecated and is now a "+
|
||||||
"subcommand for interacting with auth methods. To authenticate "+
|
"subcommand for interacting with auth methods. To authenticate "+
|
||||||
"locally to Vault, use \"vault login\" instead. This backwards "+
|
"locally to Vault, use \"vault login\" instead. This backwards "+
|
||||||
"compatibility will be removed in Vault 0.11 (or later).") + "\n")
|
"compatibility will be removed in Vault 0.11 (or later).") + "\n")
|
||||||
|
}
|
||||||
return (&LoginCommand{
|
return (&LoginCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: &BaseCommand{
|
||||||
UI: c.UI,
|
UI: c.UI,
|
||||||
|
|
|
@ -284,7 +284,7 @@ func (c *BaseCommand) flagSet(bit FlagSetBit) *FlagSets {
|
||||||
Usage: "Print only the field with the given name. Specifying " +
|
Usage: "Print only the field with the given name. Specifying " +
|
||||||
"this option will take precedence over other formatting " +
|
"this option will take precedence over other formatting " +
|
||||||
"directives. The result will not have a trailing newline " +
|
"directives. The result will not have a trailing newline " +
|
||||||
"making it idea for piping to other processes.",
|
"making it ideal for piping to other processes.",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
ad "github.com/hashicorp/vault-plugin-secrets-ad/plugin"
|
||||||
gcp "github.com/hashicorp/vault-plugin-secrets-gcp/plugin"
|
gcp "github.com/hashicorp/vault-plugin-secrets-gcp/plugin"
|
||||||
kv "github.com/hashicorp/vault-plugin-secrets-kv"
|
kv "github.com/hashicorp/vault-plugin-secrets-kv"
|
||||||
"github.com/hashicorp/vault/audit"
|
"github.com/hashicorp/vault/audit"
|
||||||
|
@ -110,6 +111,7 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
logicalBackends = map[string]logical.Factory{
|
logicalBackends = map[string]logical.Factory{
|
||||||
|
"ad": ad.Factory,
|
||||||
"aws": aws.Factory,
|
"aws": aws.Factory,
|
||||||
"cassandra": cassandra.Factory,
|
"cassandra": cassandra.Factory,
|
||||||
"consul": consul.Factory,
|
"consul": consul.Factory,
|
||||||
|
@ -211,359 +213,212 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands = map[string]cli.CommandFactory{
|
getBaseCommand := func() *BaseCommand {
|
||||||
"audit": func() (cli.Command, error) {
|
return &BaseCommand{
|
||||||
return &AuditCommand{
|
|
||||||
BaseCommand: &BaseCommand{
|
|
||||||
UI: ui,
|
UI: ui,
|
||||||
tokenHelper: runOpts.TokenHelper,
|
tokenHelper: runOpts.TokenHelper,
|
||||||
flagAddress: runOpts.Address,
|
flagAddress: runOpts.Address,
|
||||||
},
|
client: runOpts.Client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Commands = map[string]cli.CommandFactory{
|
||||||
|
"audit": func() (cli.Command, error) {
|
||||||
|
return &AuditCommand{
|
||||||
|
BaseCommand: getBaseCommand(),
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"audit disable": func() (cli.Command, error) {
|
"audit disable": func() (cli.Command, error) {
|
||||||
return &AuditDisableCommand{
|
return &AuditDisableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"audit enable": func() (cli.Command, error) {
|
"audit enable": func() (cli.Command, error) {
|
||||||
return &AuditEnableCommand{
|
return &AuditEnableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"audit list": func() (cli.Command, error) {
|
"audit list": func() (cli.Command, error) {
|
||||||
return &AuditListCommand{
|
return &AuditListCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"auth tune": func() (cli.Command, error) {
|
"auth tune": func() (cli.Command, error) {
|
||||||
return &AuthTuneCommand{
|
return &AuthTuneCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"auth": func() (cli.Command, error) {
|
"auth": func() (cli.Command, error) {
|
||||||
return &AuthCommand{
|
return &AuthCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
Handlers: loginHandlers,
|
Handlers: loginHandlers,
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"auth disable": func() (cli.Command, error) {
|
"auth disable": func() (cli.Command, error) {
|
||||||
return &AuthDisableCommand{
|
return &AuthDisableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"auth enable": func() (cli.Command, error) {
|
"auth enable": func() (cli.Command, error) {
|
||||||
return &AuthEnableCommand{
|
return &AuthEnableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"auth help": func() (cli.Command, error) {
|
"auth help": func() (cli.Command, error) {
|
||||||
return &AuthHelpCommand{
|
return &AuthHelpCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
Handlers: loginHandlers,
|
Handlers: loginHandlers,
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"auth list": func() (cli.Command, error) {
|
"auth list": func() (cli.Command, error) {
|
||||||
return &AuthListCommand{
|
return &AuthListCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"delete": func() (cli.Command, error) {
|
"delete": func() (cli.Command, error) {
|
||||||
return &DeleteCommand{
|
return &DeleteCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"lease": func() (cli.Command, error) {
|
"lease": func() (cli.Command, error) {
|
||||||
return &LeaseCommand{
|
return &LeaseCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"lease renew": func() (cli.Command, error) {
|
"lease renew": func() (cli.Command, error) {
|
||||||
return &LeaseRenewCommand{
|
return &LeaseRenewCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"lease revoke": func() (cli.Command, error) {
|
"lease revoke": func() (cli.Command, error) {
|
||||||
return &LeaseRevokeCommand{
|
return &LeaseRevokeCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"list": func() (cli.Command, error) {
|
"list": func() (cli.Command, error) {
|
||||||
return &ListCommand{
|
return &ListCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"login": func() (cli.Command, error) {
|
"login": func() (cli.Command, error) {
|
||||||
return &LoginCommand{
|
return &LoginCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
Handlers: loginHandlers,
|
Handlers: loginHandlers,
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"operator": func() (cli.Command, error) {
|
"operator": func() (cli.Command, error) {
|
||||||
return &OperatorCommand{
|
return &OperatorCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"operator generate-root": func() (cli.Command, error) {
|
"operator generate-root": func() (cli.Command, error) {
|
||||||
return &OperatorGenerateRootCommand{
|
return &OperatorGenerateRootCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"operator init": func() (cli.Command, error) {
|
"operator init": func() (cli.Command, error) {
|
||||||
return &OperatorInitCommand{
|
return &OperatorInitCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"operator key-status": func() (cli.Command, error) {
|
"operator key-status": func() (cli.Command, error) {
|
||||||
return &OperatorKeyStatusCommand{
|
return &OperatorKeyStatusCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"operator rekey": func() (cli.Command, error) {
|
"operator rekey": func() (cli.Command, error) {
|
||||||
return &OperatorRekeyCommand{
|
return &OperatorRekeyCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"operator rotate": func() (cli.Command, error) {
|
"operator rotate": func() (cli.Command, error) {
|
||||||
return &OperatorRotateCommand{
|
return &OperatorRotateCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"operator seal": func() (cli.Command, error) {
|
"operator seal": func() (cli.Command, error) {
|
||||||
return &OperatorSealCommand{
|
return &OperatorSealCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"operator step-down": func() (cli.Command, error) {
|
"operator step-down": func() (cli.Command, error) {
|
||||||
return &OperatorStepDownCommand{
|
return &OperatorStepDownCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"operator unseal": func() (cli.Command, error) {
|
"operator unseal": func() (cli.Command, error) {
|
||||||
return &OperatorUnsealCommand{
|
return &OperatorUnsealCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"path-help": func() (cli.Command, error) {
|
"path-help": func() (cli.Command, error) {
|
||||||
return &PathHelpCommand{
|
return &PathHelpCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"policy": func() (cli.Command, error) {
|
"policy": func() (cli.Command, error) {
|
||||||
return &PolicyCommand{
|
return &PolicyCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"policy delete": func() (cli.Command, error) {
|
"policy delete": func() (cli.Command, error) {
|
||||||
return &PolicyDeleteCommand{
|
return &PolicyDeleteCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"policy fmt": func() (cli.Command, error) {
|
"policy fmt": func() (cli.Command, error) {
|
||||||
return &PolicyFmtCommand{
|
return &PolicyFmtCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"policy list": func() (cli.Command, error) {
|
"policy list": func() (cli.Command, error) {
|
||||||
return &PolicyListCommand{
|
return &PolicyListCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"policy read": func() (cli.Command, error) {
|
"policy read": func() (cli.Command, error) {
|
||||||
return &PolicyReadCommand{
|
return &PolicyReadCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"policy write": func() (cli.Command, error) {
|
"policy write": func() (cli.Command, error) {
|
||||||
return &PolicyWriteCommand{
|
return &PolicyWriteCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"read": func() (cli.Command, error) {
|
"read": func() (cli.Command, error) {
|
||||||
return &ReadCommand{
|
return &ReadCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"secrets": func() (cli.Command, error) {
|
"secrets": func() (cli.Command, error) {
|
||||||
return &SecretsCommand{
|
return &SecretsCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"secrets disable": func() (cli.Command, error) {
|
"secrets disable": func() (cli.Command, error) {
|
||||||
return &SecretsDisableCommand{
|
return &SecretsDisableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"secrets enable": func() (cli.Command, error) {
|
"secrets enable": func() (cli.Command, error) {
|
||||||
return &SecretsEnableCommand{
|
return &SecretsEnableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"secrets list": func() (cli.Command, error) {
|
"secrets list": func() (cli.Command, error) {
|
||||||
return &SecretsListCommand{
|
return &SecretsListCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"secrets move": func() (cli.Command, error) {
|
"secrets move": func() (cli.Command, error) {
|
||||||
return &SecretsMoveCommand{
|
return &SecretsMoveCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"secrets tune": func() (cli.Command, error) {
|
"secrets tune": func() (cli.Command, error) {
|
||||||
return &SecretsTuneCommand{
|
return &SecretsTuneCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"server": func() (cli.Command, error) {
|
"server": func() (cli.Command, error) {
|
||||||
|
@ -583,193 +438,123 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
},
|
},
|
||||||
"ssh": func() (cli.Command, error) {
|
"ssh": func() (cli.Command, error) {
|
||||||
return &SSHCommand{
|
return &SSHCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"status": func() (cli.Command, error) {
|
"status": func() (cli.Command, error) {
|
||||||
return &StatusCommand{
|
return &StatusCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"token": func() (cli.Command, error) {
|
"token": func() (cli.Command, error) {
|
||||||
return &TokenCommand{
|
return &TokenCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"token create": func() (cli.Command, error) {
|
"token create": func() (cli.Command, error) {
|
||||||
return &TokenCreateCommand{
|
return &TokenCreateCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"token capabilities": func() (cli.Command, error) {
|
"token capabilities": func() (cli.Command, error) {
|
||||||
return &TokenCapabilitiesCommand{
|
return &TokenCapabilitiesCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"token lookup": func() (cli.Command, error) {
|
"token lookup": func() (cli.Command, error) {
|
||||||
return &TokenLookupCommand{
|
return &TokenLookupCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"token renew": func() (cli.Command, error) {
|
"token renew": func() (cli.Command, error) {
|
||||||
return &TokenRenewCommand{
|
return &TokenRenewCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"token revoke": func() (cli.Command, error) {
|
"token revoke": func() (cli.Command, error) {
|
||||||
return &TokenRevokeCommand{
|
return &TokenRevokeCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"unwrap": func() (cli.Command, error) {
|
"unwrap": func() (cli.Command, error) {
|
||||||
return &UnwrapCommand{
|
return &UnwrapCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"version": func() (cli.Command, error) {
|
"version": func() (cli.Command, error) {
|
||||||
return &VersionCommand{
|
return &VersionCommand{
|
||||||
VersionInfo: version.GetVersion(),
|
VersionInfo: version.GetVersion(),
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"write": func() (cli.Command, error) {
|
"write": func() (cli.Command, error) {
|
||||||
return &WriteCommand{
|
return &WriteCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv": func() (cli.Command, error) {
|
"kv": func() (cli.Command, error) {
|
||||||
return &KVCommand{
|
return &KVCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv put": func() (cli.Command, error) {
|
"kv put": func() (cli.Command, error) {
|
||||||
return &KVPutCommand{
|
return &KVPutCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv patch": func() (cli.Command, error) {
|
"kv patch": func() (cli.Command, error) {
|
||||||
return &KVPatchCommand{
|
return &KVPatchCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv get": func() (cli.Command, error) {
|
"kv get": func() (cli.Command, error) {
|
||||||
return &KVGetCommand{
|
return &KVGetCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv delete": func() (cli.Command, error) {
|
"kv delete": func() (cli.Command, error) {
|
||||||
return &KVDeleteCommand{
|
return &KVDeleteCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv list": func() (cli.Command, error) {
|
"kv list": func() (cli.Command, error) {
|
||||||
return &KVListCommand{
|
return &KVListCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv destroy": func() (cli.Command, error) {
|
"kv destroy": func() (cli.Command, error) {
|
||||||
return &KVDestroyCommand{
|
return &KVDestroyCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv undelete": func() (cli.Command, error) {
|
"kv undelete": func() (cli.Command, error) {
|
||||||
return &KVUndeleteCommand{
|
return &KVUndeleteCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv enable-versioning": func() (cli.Command, error) {
|
"kv enable-versioning": func() (cli.Command, error) {
|
||||||
return &KVEnableVersioningCommand{
|
return &KVEnableVersioningCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv metadata": func() (cli.Command, error) {
|
"kv metadata": func() (cli.Command, error) {
|
||||||
return &KVMetadataCommand{
|
return &KVMetadataCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv metadata put": func() (cli.Command, error) {
|
"kv metadata put": func() (cli.Command, error) {
|
||||||
return &KVMetadataPutCommand{
|
return &KVMetadataPutCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv metadata get": func() (cli.Command, error) {
|
"kv metadata get": func() (cli.Command, error) {
|
||||||
return &KVMetadataGetCommand{
|
return &KVMetadataGetCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
"kv metadata delete": func() (cli.Command, error) {
|
"kv metadata delete": func() (cli.Command, error) {
|
||||||
return &KVMetadataDeleteCommand{
|
return &KVMetadataDeleteCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -782,12 +567,9 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
return &DeprecatedCommand{
|
return &DeprecatedCommand{
|
||||||
Old: "audit-disable",
|
Old: "audit-disable",
|
||||||
New: "audit disable",
|
New: "audit disable",
|
||||||
Command: &AuditDisableCommand{
|
|
||||||
BaseCommand: &BaseCommand{
|
|
||||||
UI: ui,
|
UI: ui,
|
||||||
tokenHelper: runOpts.TokenHelper,
|
Command: &AuditDisableCommand{
|
||||||
flagAddress: runOpts.Address,
|
BaseCommand: getBaseCommand(),
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -798,11 +580,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "audit enable",
|
New: "audit enable",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &AuditEnableCommand{
|
Command: &AuditEnableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -813,11 +591,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "audit list",
|
New: "audit list",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &AuditListCommand{
|
Command: &AuditListCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -828,11 +602,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "auth disable",
|
New: "auth disable",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &AuthDisableCommand{
|
Command: &AuthDisableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -843,11 +613,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "auth enable",
|
New: "auth enable",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &AuthEnableCommand{
|
Command: &AuthEnableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -858,11 +624,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "token capabilities",
|
New: "token capabilities",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &TokenCapabilitiesCommand{
|
Command: &TokenCapabilitiesCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -873,11 +635,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "operator generate-root",
|
New: "operator generate-root",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &OperatorGenerateRootCommand{
|
Command: &OperatorGenerateRootCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -888,11 +646,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "operator init",
|
New: "operator init",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &OperatorInitCommand{
|
Command: &OperatorInitCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -903,11 +657,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "operator key-status",
|
New: "operator key-status",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &OperatorKeyStatusCommand{
|
Command: &OperatorKeyStatusCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -918,11 +668,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "lease renew",
|
New: "lease renew",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &LeaseRenewCommand{
|
Command: &LeaseRenewCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -933,11 +679,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "lease revoke",
|
New: "lease revoke",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &LeaseRevokeCommand{
|
Command: &LeaseRevokeCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -948,11 +690,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "secrets enable",
|
New: "secrets enable",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &SecretsEnableCommand{
|
Command: &SecretsEnableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -963,11 +701,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "secrets tune",
|
New: "secrets tune",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &SecretsTuneCommand{
|
Command: &SecretsTuneCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -978,11 +712,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "secrets list",
|
New: "secrets list",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &SecretsListCommand{
|
Command: &SecretsListCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -993,11 +723,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "policy read\" or \"vault policy list", // lol
|
New: "policy read\" or \"vault policy list", // lol
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &PoliciesDeprecatedCommand{
|
Command: &PoliciesDeprecatedCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1008,11 +734,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "policy delete",
|
New: "policy delete",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &PolicyDeleteCommand{
|
Command: &PolicyDeleteCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1023,11 +745,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "policy write",
|
New: "policy write",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &PolicyWriteCommand{
|
Command: &PolicyWriteCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1038,11 +756,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "operator rekey",
|
New: "operator rekey",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &OperatorRekeyCommand{
|
Command: &OperatorRekeyCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1053,11 +767,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "secrets move",
|
New: "secrets move",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &SecretsMoveCommand{
|
Command: &SecretsMoveCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1068,11 +778,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "operator rotate",
|
New: "operator rotate",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &OperatorRotateCommand{
|
Command: &OperatorRotateCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1083,11 +789,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "operator seal",
|
New: "operator seal",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &OperatorSealCommand{
|
Command: &OperatorSealCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1098,11 +800,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "operator step-down",
|
New: "operator step-down",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &OperatorStepDownCommand{
|
Command: &OperatorStepDownCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1113,11 +811,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "token create",
|
New: "token create",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &TokenCreateCommand{
|
Command: &TokenCreateCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1128,11 +822,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "token lookup",
|
New: "token lookup",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &TokenLookupCommand{
|
Command: &TokenLookupCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1143,11 +833,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "token renew",
|
New: "token renew",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &TokenRenewCommand{
|
Command: &TokenRenewCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1158,11 +844,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "token revoke",
|
New: "token revoke",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &TokenRevokeCommand{
|
Command: &TokenRevokeCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1173,11 +855,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "secrets disable",
|
New: "secrets disable",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &SecretsDisableCommand{
|
Command: &SecretsDisableCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
@ -1188,11 +866,7 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||||
New: "operator unseal",
|
New: "operator unseal",
|
||||||
UI: ui,
|
UI: ui,
|
||||||
Command: &OperatorUnsealCommand{
|
Command: &OperatorUnsealCommand{
|
||||||
BaseCommand: &BaseCommand{
|
BaseCommand: getBaseCommand(),
|
||||||
UI: ui,
|
|
||||||
tokenHelper: runOpts.TokenHelper,
|
|
||||||
flagAddress: runOpts.Address,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
|
@ -69,20 +69,18 @@ var Formatters = map[string]Formatter{
|
||||||
"yml": YamlFormatter{},
|
"yml": YamlFormatter{},
|
||||||
}
|
}
|
||||||
|
|
||||||
func format() string {
|
|
||||||
format := os.Getenv(EnvVaultFormat)
|
|
||||||
if format == "" {
|
|
||||||
format = "table"
|
|
||||||
}
|
|
||||||
return format
|
|
||||||
}
|
|
||||||
|
|
||||||
func Format(ui cli.Ui) string {
|
func Format(ui cli.Ui) string {
|
||||||
switch ui.(type) {
|
switch ui.(type) {
|
||||||
case *VaultUI:
|
case *VaultUI:
|
||||||
return ui.(*VaultUI).format
|
return ui.(*VaultUI).format
|
||||||
}
|
}
|
||||||
return format()
|
|
||||||
|
format := os.Getenv(EnvVaultFormat)
|
||||||
|
if format == "" {
|
||||||
|
format = "table"
|
||||||
|
}
|
||||||
|
|
||||||
|
return format
|
||||||
}
|
}
|
||||||
|
|
||||||
// An output formatter for json output of an object
|
// An output formatter for json output of an object
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -91,13 +92,13 @@ func Test_Format_Parsing(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"format",
|
"format",
|
||||||
[]string{"-format", "json"},
|
[]string{"token", "renew", "-format", "json"},
|
||||||
"{",
|
"{",
|
||||||
0,
|
0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"format_bad",
|
"format_bad",
|
||||||
[]string{"-format", "nope-not-real"},
|
[]string{"token", "renew", "-format", "nope-not-real"},
|
||||||
"Invalid output format",
|
"Invalid output format",
|
||||||
1,
|
1,
|
||||||
},
|
},
|
||||||
|
@ -110,21 +111,24 @@ func Test_Format_Parsing(t *testing.T) {
|
||||||
client, closer := testVaultServer(t)
|
client, closer := testVaultServer(t)
|
||||||
defer closer()
|
defer closer()
|
||||||
|
|
||||||
|
stdout := bytes.NewBuffer(nil)
|
||||||
|
stderr := bytes.NewBuffer(nil)
|
||||||
|
runOpts := &RunOptions{
|
||||||
|
Stdout: stdout,
|
||||||
|
Stderr: stderr,
|
||||||
|
Client: client,
|
||||||
|
}
|
||||||
|
|
||||||
// Login with the token so we can renew-self.
|
// Login with the token so we can renew-self.
|
||||||
token, _ := testTokenAndAccessor(t, client)
|
token, _ := testTokenAndAccessor(t, client)
|
||||||
client.SetToken(token)
|
client.SetToken(token)
|
||||||
|
|
||||||
ui, cmd := testTokenRenewCommand(t)
|
code := RunCustom(tc.args, runOpts)
|
||||||
cmd.client = client
|
|
||||||
|
|
||||||
tc.args = setupEnv(tc.args)
|
|
||||||
|
|
||||||
code := cmd.Run(tc.args)
|
|
||||||
if code != tc.code {
|
if code != tc.code {
|
||||||
t.Errorf("expected %d to be %d", code, tc.code)
|
t.Errorf("expected %d to be %d", code, tc.code)
|
||||||
}
|
}
|
||||||
|
|
||||||
combined := ui.OutputWriter.String() + ui.ErrorWriter.String()
|
combined := stdout.String() + stderr.String()
|
||||||
if !strings.Contains(combined, tc.out) {
|
if !strings.Contains(combined, tc.out) {
|
||||||
t.Errorf("expected %q to contain %q", combined, tc.out)
|
t.Errorf("expected %q to contain %q", combined, tc.out)
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,11 +94,12 @@ func (c *LeaseRenewCommand) Run(args []string) int {
|
||||||
case 2:
|
case 2:
|
||||||
// Deprecation
|
// Deprecation
|
||||||
// TODO: remove in 0.9.0
|
// TODO: remove in 0.9.0
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"WARNING! Specifying INCREMENT as a second argument is deprecated. " +
|
"WARNING! Specifying INCREMENT as a second argument is deprecated. " +
|
||||||
"Please use -increment instead. This will be removed in the next " +
|
"Please use -increment instead. This will be removed in the next " +
|
||||||
"major release of Vault."))
|
"major release of Vault."))
|
||||||
|
}
|
||||||
leaseID = strings.TrimSpace(args[0])
|
leaseID = strings.TrimSpace(args[0])
|
||||||
parsed, err := time.ParseDuration(appendDurationSuffix(args[1]))
|
parsed, err := time.ParseDuration(appendDurationSuffix(args[1]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -167,6 +167,7 @@ func (c *LoginCommand) Run(args []string) int {
|
||||||
// TODO: remove in 0.10.0
|
// TODO: remove in 0.10.0
|
||||||
switch {
|
switch {
|
||||||
case c.flagNoVerify:
|
case c.flagNoVerify:
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"WARNING! The -no-verify flag is deprecated. In the past, Vault " +
|
"WARNING! The -no-verify flag is deprecated. In the past, Vault " +
|
||||||
"performed a lookup on a token after authentication. This is no " +
|
"performed a lookup on a token after authentication. This is no " +
|
||||||
|
@ -187,6 +188,7 @@ func (c *LoginCommand) Run(args []string) int {
|
||||||
"If you are not using token authentication, you can safely omit this " +
|
"If you are not using token authentication, you can safely omit this " +
|
||||||
"flag. Vault will not perform a lookup after authentication."))
|
"flag. Vault will not perform a lookup after authentication."))
|
||||||
c.UI.Warn("")
|
c.UI.Warn("")
|
||||||
|
}
|
||||||
|
|
||||||
// There's no point in passing this to other auth handlers...
|
// There's no point in passing this to other auth handlers...
|
||||||
if c.flagMethod == "token" {
|
if c.flagMethod == "token" {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
|
"github.com/hashicorp/vault/api"
|
||||||
"github.com/hashicorp/vault/command/token"
|
"github.com/hashicorp/vault/command/token"
|
||||||
colorable "github.com/mattn/go-colorable"
|
colorable "github.com/mattn/go-colorable"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
|
@ -22,8 +23,7 @@ type VaultUI struct {
|
||||||
|
|
||||||
// setupEnv parses args and may replace them and sets some env vars to known
|
// setupEnv parses args and may replace them and sets some env vars to known
|
||||||
// values based on format options
|
// values based on format options
|
||||||
func setupEnv(args []string) []string {
|
func setupEnv(args []string) (retArgs []string, format string) {
|
||||||
var format string
|
|
||||||
var nextArgFormat bool
|
var nextArgFormat bool
|
||||||
|
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
|
@ -65,10 +65,8 @@ func setupEnv(args []string) []string {
|
||||||
if format == "" {
|
if format == "" {
|
||||||
format = "table"
|
format = "table"
|
||||||
}
|
}
|
||||||
// Put back into the env for later
|
|
||||||
os.Setenv(EnvVaultFormat, format)
|
|
||||||
|
|
||||||
return args
|
return args, format
|
||||||
}
|
}
|
||||||
|
|
||||||
type RunOptions struct {
|
type RunOptions struct {
|
||||||
|
@ -76,6 +74,7 @@ type RunOptions struct {
|
||||||
Stdout io.Writer
|
Stdout io.Writer
|
||||||
Stderr io.Writer
|
Stderr io.Writer
|
||||||
Address string
|
Address string
|
||||||
|
Client *api.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run(args []string) int {
|
func Run(args []string) int {
|
||||||
|
@ -89,7 +88,8 @@ func RunCustom(args []string, runOpts *RunOptions) int {
|
||||||
runOpts = &RunOptions{}
|
runOpts = &RunOptions{}
|
||||||
}
|
}
|
||||||
|
|
||||||
args = setupEnv(args)
|
var format string
|
||||||
|
args, format = setupEnv(args)
|
||||||
|
|
||||||
// Don't use color if disabled
|
// Don't use color if disabled
|
||||||
useColor := true
|
useColor := true
|
||||||
|
@ -104,8 +104,6 @@ func RunCustom(args []string, runOpts *RunOptions) int {
|
||||||
runOpts.Stderr = os.Stderr
|
runOpts.Stderr = os.Stderr
|
||||||
}
|
}
|
||||||
|
|
||||||
format := format()
|
|
||||||
|
|
||||||
// Only use colored UI if stdout is a tty, and not disabled
|
// Only use colored UI if stdout is a tty, and not disabled
|
||||||
if useColor && format == "table" {
|
if useColor && format == "table" {
|
||||||
if f, ok := runOpts.Stdout.(*os.File); ok {
|
if f, ok := runOpts.Stdout.(*os.File); ok {
|
||||||
|
|
|
@ -217,9 +217,11 @@ func (c *OperatorGenerateRootCommand) Run(args []string) int {
|
||||||
// TODO: remove in 0.9.0
|
// TODO: remove in 0.9.0
|
||||||
switch {
|
switch {
|
||||||
case c.flagGenOTP:
|
case c.flagGenOTP:
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"The -gen-otp flag is deprecated. Please use the -generate-otp flag " +
|
"WARNING! The -gen-otp flag is deprecated. Please use the -generate-otp flag " +
|
||||||
"instead."))
|
"instead."))
|
||||||
|
}
|
||||||
c.flagGenerateOTP = c.flagGenOTP
|
c.flagGenerateOTP = c.flagGenOTP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,14 +244,18 @@ func (c *OperatorInitCommand) Run(args []string) int {
|
||||||
// Deprecations
|
// Deprecations
|
||||||
// TODO: remove in 0.9.0
|
// TODO: remove in 0.9.0
|
||||||
if c.flagAuto {
|
if c.flagAuto {
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength("WARNING! -auto is deprecated. Please use " +
|
c.UI.Warn(wrapAtLength("WARNING! -auto is deprecated. Please use " +
|
||||||
"-consul-auto instead. This will be removed in Vault 0.11 " +
|
"-consul-auto instead. This will be removed in Vault 0.11 " +
|
||||||
"(or later)."))
|
"(or later)."))
|
||||||
|
}
|
||||||
c.flagConsulAuto = true
|
c.flagConsulAuto = true
|
||||||
}
|
}
|
||||||
if c.flagCheck {
|
if c.flagCheck {
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength("WARNING! -check is deprecated. Please use " +
|
c.UI.Warn(wrapAtLength("WARNING! -check is deprecated. Please use " +
|
||||||
"-status instead. This will be removed in Vault 0.11 (or later)."))
|
"-status instead. This will be removed in Vault 0.11 (or later)."))
|
||||||
|
}
|
||||||
c.flagStatus = true
|
c.flagStatus = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,21 +269,27 @@ func (c *OperatorRekeyCommand) Run(args []string) int {
|
||||||
// Deprecations
|
// Deprecations
|
||||||
// TODO: remove in 0.9.0
|
// TODO: remove in 0.9.0
|
||||||
if c.flagDelete {
|
if c.flagDelete {
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"WARNING! The -delete flag is deprecated. Please use -backup-delete " +
|
"WARNING! The -delete flag is deprecated. Please use -backup-delete " +
|
||||||
"instead. This flag will be removed in Vault 0.11 (or later)."))
|
"instead. This flag will be removed in Vault 0.11 (or later)."))
|
||||||
|
}
|
||||||
c.flagBackupDelete = true
|
c.flagBackupDelete = true
|
||||||
}
|
}
|
||||||
if c.flagRetrieve {
|
if c.flagRetrieve {
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"WARNING! The -retrieve flag is deprecated. Please use -backup-retrieve " +
|
"WARNING! The -retrieve flag is deprecated. Please use -backup-retrieve " +
|
||||||
"instead. This flag will be removed in Vault 0.11 (or later)."))
|
"instead. This flag will be removed in Vault 0.11 (or later)."))
|
||||||
|
}
|
||||||
c.flagBackupRetrieve = true
|
c.flagBackupRetrieve = true
|
||||||
}
|
}
|
||||||
if c.flagRecoveryKey {
|
if c.flagRecoveryKey {
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"WARNING! The -recovery-key flag is deprecated. Please use -target=recovery " +
|
"WARNING! The -recovery-key flag is deprecated. Please use -target=recovery " +
|
||||||
"instead. This flag will be removed in Vault 0.11 (or later)."))
|
"instead. This flag will be removed in Vault 0.11 (or later)."))
|
||||||
|
}
|
||||||
c.flagTarget = "recovery"
|
c.flagTarget = "recovery"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,6 +350,7 @@ func (c *OperatorRekeyCommand) init(client *api.Client) int {
|
||||||
|
|
||||||
// Print warnings about recovery, etc.
|
// Print warnings about recovery, etc.
|
||||||
if len(c.flagPGPKeys) == 0 {
|
if len(c.flagPGPKeys) == 0 {
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"WARNING! If you lose the keys after they are returned, there is no " +
|
"WARNING! If you lose the keys after they are returned, there is no " +
|
||||||
"recovery. Consider canceling this operation and re-initializing " +
|
"recovery. Consider canceling this operation and re-initializing " +
|
||||||
|
@ -353,7 +360,9 @@ func (c *OperatorRekeyCommand) init(client *api.Client) int {
|
||||||
"flag."))
|
"flag."))
|
||||||
c.UI.Output("")
|
c.UI.Output("")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if len(c.flagPGPKeys) > 0 && !c.flagBackup {
|
if len(c.flagPGPKeys) > 0 && !c.flagBackup {
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn(wrapAtLength(
|
c.UI.Warn(wrapAtLength(
|
||||||
"WARNING! You are using PGP keys for encrypted the resulting unseal " +
|
"WARNING! You are using PGP keys for encrypted the resulting unseal " +
|
||||||
"keys, but you did not enable the option to backup the keys to " +
|
"keys, but you did not enable the option to backup the keys to " +
|
||||||
|
@ -364,6 +373,7 @@ func (c *OperatorRekeyCommand) init(client *api.Client) int {
|
||||||
"stored keys later using the -delete flag."))
|
"stored keys later using the -delete flag."))
|
||||||
c.UI.Output("")
|
c.UI.Output("")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Provide the current status
|
// Provide the current status
|
||||||
return c.printStatus(status)
|
return c.printStatus(status)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -147,7 +148,6 @@ func TestOperatorUnsealCommand_Run(t *testing.T) {
|
||||||
|
|
||||||
func TestOperatorUnsealCommand_Format(t *testing.T) {
|
func TestOperatorUnsealCommand_Format(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
os.Setenv(EnvVaultFormat, "")
|
|
||||||
os.Setenv(EnvVaultCLINoColor, "")
|
os.Setenv(EnvVaultCLINoColor, "")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -159,21 +159,28 @@ func TestOperatorUnsealCommand_Format(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ui, cmd := testOperatorUnsealCommand(t)
|
stdout := bytes.NewBuffer(nil)
|
||||||
cmd.client = client
|
stderr := bytes.NewBuffer(nil)
|
||||||
cmd.testOutput = ioutil.Discard
|
runOpts := &RunOptions{
|
||||||
|
Stdout: stdout,
|
||||||
args := setupEnv([]string{"-format", "json"})
|
Stderr: stderr,
|
||||||
|
Client: client,
|
||||||
// Unseal with one key
|
|
||||||
code := cmd.Run(append(args, []string{
|
|
||||||
keys[0],
|
|
||||||
}...))
|
|
||||||
if exp := 0; code != exp {
|
|
||||||
t.Errorf("expected %d to be %d: %s", code, exp, ui.ErrorWriter.String())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !json.Valid(ui.OutputWriter.Bytes()) {
|
args, format := setupEnv([]string{"unseal", "-format", "json"})
|
||||||
|
if format != "json" {
|
||||||
|
t.Fatalf("expected %q, got %q", "json", format)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unseal with one key
|
||||||
|
code := RunCustom(append(args, []string{
|
||||||
|
keys[0],
|
||||||
|
}...), runOpts)
|
||||||
|
if exp := 0; code != exp {
|
||||||
|
t.Errorf("expected %d to be %d: %s", code, exp, stderr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !json.Valid(stdout.Bytes()) {
|
||||||
t.Error("expected output to be valid JSON")
|
t.Error("expected output to be valid JSON")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,9 +207,11 @@ func (c *TokenCreateCommand) Run(args []string) int {
|
||||||
|
|
||||||
// TODO: remove in 0.9.0
|
// TODO: remove in 0.9.0
|
||||||
if c.flagLease != 0 {
|
if c.flagLease != 0 {
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn("The -lease flag is deprecated. Please use -ttl instead.")
|
c.UI.Warn("The -lease flag is deprecated. Please use -ttl instead.")
|
||||||
c.flagTTL = c.flagLease
|
c.flagTTL = c.flagLease
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
client, err := c.Client()
|
client, err := c.Client()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -99,9 +99,10 @@ func (c *TokenRenewCommand) Run(args []string) int {
|
||||||
token = strings.TrimSpace(args[0])
|
token = strings.TrimSpace(args[0])
|
||||||
case 2:
|
case 2:
|
||||||
// TODO: remove in 0.9.0 - backwards compat
|
// TODO: remove in 0.9.0 - backwards compat
|
||||||
|
if Format(c.UI) == "table" {
|
||||||
c.UI.Warn("Specifying increment as a second argument is deprecated. " +
|
c.UI.Warn("Specifying increment as a second argument is deprecated. " +
|
||||||
"Please use -increment instead.")
|
"Please use -increment instead.")
|
||||||
|
}
|
||||||
token = strings.TrimSpace(args[0])
|
token = strings.TrimSpace(args[0])
|
||||||
parsed, err := time.ParseDuration(appendDurationSuffix(args[1]))
|
parsed, err := time.ParseDuration(appendDurationSuffix(args[1]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -5,10 +5,235 @@ import (
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/helper/tlsutil"
|
"github.com/hashicorp/vault/helper/tlsutil"
|
||||||
|
"github.com/hashicorp/vault/logical/framework"
|
||||||
|
|
||||||
|
"github.com/hashicorp/errwrap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ConfigFields returns all the config fields that can potentially be used by the LDAP client.
|
||||||
|
// Not all fields will be used by every integration.
|
||||||
|
func ConfigFields() map[string]*framework.FieldSchema {
|
||||||
|
return map[string]*framework.FieldSchema{
|
||||||
|
"url": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Default: "ldap://127.0.0.1",
|
||||||
|
Description: "LDAP URL to connect to (default: ldap://127.0.0.1). Multiple URLs can be specified by concatenating them with commas; they will be tried in-order.",
|
||||||
|
},
|
||||||
|
|
||||||
|
"userdn": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: "LDAP domain to use for users (eg: ou=People,dc=example,dc=org)",
|
||||||
|
},
|
||||||
|
|
||||||
|
"binddn": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: "LDAP DN for searching for the user DN (optional)",
|
||||||
|
},
|
||||||
|
|
||||||
|
"bindpass": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: "LDAP password for searching for the user DN (optional)",
|
||||||
|
},
|
||||||
|
|
||||||
|
"groupdn": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: "LDAP search base to use for group membership search (eg: ou=Groups,dc=example,dc=org)",
|
||||||
|
},
|
||||||
|
|
||||||
|
"groupfilter": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Default: "(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))",
|
||||||
|
Description: `Go template for querying group membership of user (optional)
|
||||||
|
The template can access the following context variables: UserDN, Username
|
||||||
|
Example: (&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))
|
||||||
|
Default: (|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))`,
|
||||||
|
},
|
||||||
|
|
||||||
|
"groupattr": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Default: "cn",
|
||||||
|
Description: `LDAP attribute to follow on objects returned by <groupfilter>
|
||||||
|
in order to enumerate user group membership.
|
||||||
|
Examples: "cn" or "memberOf", etc.
|
||||||
|
Default: cn`,
|
||||||
|
},
|
||||||
|
|
||||||
|
"upndomain": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: "Enables userPrincipalDomain login with [username]@UPNDomain (optional)",
|
||||||
|
},
|
||||||
|
|
||||||
|
"userattr": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Default: "cn",
|
||||||
|
Description: "Attribute used for users (default: cn)",
|
||||||
|
},
|
||||||
|
|
||||||
|
"certificate": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: "CA certificate to use when verifying LDAP server certificate, must be x509 PEM encoded (optional)",
|
||||||
|
},
|
||||||
|
|
||||||
|
"discoverdn": {
|
||||||
|
Type: framework.TypeBool,
|
||||||
|
Description: "Use anonymous bind to discover the bind DN of a user (optional)",
|
||||||
|
},
|
||||||
|
|
||||||
|
"insecure_tls": {
|
||||||
|
Type: framework.TypeBool,
|
||||||
|
Description: "Skip LDAP server SSL Certificate verification - VERY insecure (optional)",
|
||||||
|
},
|
||||||
|
|
||||||
|
"starttls": {
|
||||||
|
Type: framework.TypeBool,
|
||||||
|
Description: "Issue a StartTLS command after establishing unencrypted connection (optional)",
|
||||||
|
},
|
||||||
|
|
||||||
|
"tls_min_version": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Default: "tls12",
|
||||||
|
Description: "Minimum TLS version to use. Accepted values are 'tls10', 'tls11' or 'tls12'. Defaults to 'tls12'",
|
||||||
|
},
|
||||||
|
|
||||||
|
"tls_max_version": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Default: "tls12",
|
||||||
|
Description: "Maximum TLS version to use. Accepted values are 'tls10', 'tls11' or 'tls12'. Defaults to 'tls12'",
|
||||||
|
},
|
||||||
|
|
||||||
|
"deny_null_bind": {
|
||||||
|
Type: framework.TypeBool,
|
||||||
|
Default: true,
|
||||||
|
Description: "Denies an unauthenticated LDAP bind request if the user's password is empty; defaults to true",
|
||||||
|
},
|
||||||
|
|
||||||
|
"case_sensitive_names": {
|
||||||
|
Type: framework.TypeBool,
|
||||||
|
Description: "If true, case sensitivity will be used when comparing usernames and groups for matching policies.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates and initializes a ConfigEntry object with its default values,
|
||||||
|
* as specified by the passed schema.
|
||||||
|
*/
|
||||||
|
func NewConfigEntry(d *framework.FieldData) (*ConfigEntry, error) {
|
||||||
|
cfg := new(ConfigEntry)
|
||||||
|
|
||||||
|
url := d.Get("url").(string)
|
||||||
|
if url != "" {
|
||||||
|
cfg.Url = strings.ToLower(url)
|
||||||
|
}
|
||||||
|
userattr := d.Get("userattr").(string)
|
||||||
|
if userattr != "" {
|
||||||
|
cfg.UserAttr = strings.ToLower(userattr)
|
||||||
|
}
|
||||||
|
userdn := d.Get("userdn").(string)
|
||||||
|
if userdn != "" {
|
||||||
|
cfg.UserDN = userdn
|
||||||
|
}
|
||||||
|
groupdn := d.Get("groupdn").(string)
|
||||||
|
if groupdn != "" {
|
||||||
|
cfg.GroupDN = groupdn
|
||||||
|
}
|
||||||
|
groupfilter := d.Get("groupfilter").(string)
|
||||||
|
if groupfilter != "" {
|
||||||
|
// Validate the template before proceeding
|
||||||
|
_, err := template.New("queryTemplate").Parse(groupfilter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errwrap.Wrapf("invalid groupfilter: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.GroupFilter = groupfilter
|
||||||
|
}
|
||||||
|
groupattr := d.Get("groupattr").(string)
|
||||||
|
if groupattr != "" {
|
||||||
|
cfg.GroupAttr = groupattr
|
||||||
|
}
|
||||||
|
upndomain := d.Get("upndomain").(string)
|
||||||
|
if upndomain != "" {
|
||||||
|
cfg.UPNDomain = upndomain
|
||||||
|
}
|
||||||
|
certificate := d.Get("certificate").(string)
|
||||||
|
if certificate != "" {
|
||||||
|
block, _ := pem.Decode([]byte(certificate))
|
||||||
|
|
||||||
|
if block == nil || block.Type != "CERTIFICATE" {
|
||||||
|
return nil, fmt.Errorf("failed to decode PEM block in the certificate")
|
||||||
|
}
|
||||||
|
_, err := x509.ParseCertificate(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errwrap.Wrapf("failed to parse certificate: {{err}}", err)
|
||||||
|
}
|
||||||
|
cfg.Certificate = certificate
|
||||||
|
}
|
||||||
|
insecureTLS := d.Get("insecure_tls").(bool)
|
||||||
|
if insecureTLS {
|
||||||
|
cfg.InsecureTLS = insecureTLS
|
||||||
|
}
|
||||||
|
cfg.TLSMinVersion = d.Get("tls_min_version").(string)
|
||||||
|
if cfg.TLSMinVersion == "" {
|
||||||
|
return nil, fmt.Errorf("failed to get 'tls_min_version' value")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ok bool
|
||||||
|
_, ok = tlsutil.TLSLookup[cfg.TLSMinVersion]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid 'tls_min_version'")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.TLSMaxVersion = d.Get("tls_max_version").(string)
|
||||||
|
if cfg.TLSMaxVersion == "" {
|
||||||
|
return nil, fmt.Errorf("failed to get 'tls_max_version' value")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok = tlsutil.TLSLookup[cfg.TLSMaxVersion]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid 'tls_max_version'")
|
||||||
|
}
|
||||||
|
if cfg.TLSMaxVersion < cfg.TLSMinVersion {
|
||||||
|
return nil, fmt.Errorf("'tls_max_version' must be greater than or equal to 'tls_min_version'")
|
||||||
|
}
|
||||||
|
|
||||||
|
startTLS := d.Get("starttls").(bool)
|
||||||
|
if startTLS {
|
||||||
|
cfg.StartTLS = startTLS
|
||||||
|
}
|
||||||
|
|
||||||
|
bindDN := d.Get("binddn").(string)
|
||||||
|
if bindDN != "" {
|
||||||
|
cfg.BindDN = bindDN
|
||||||
|
}
|
||||||
|
|
||||||
|
bindPass := d.Get("bindpass").(string)
|
||||||
|
if bindPass != "" {
|
||||||
|
cfg.BindPassword = bindPass
|
||||||
|
}
|
||||||
|
|
||||||
|
denyNullBind := d.Get("deny_null_bind").(bool)
|
||||||
|
if denyNullBind {
|
||||||
|
cfg.DenyNullBind = denyNullBind
|
||||||
|
}
|
||||||
|
|
||||||
|
discoverDN := d.Get("discoverdn").(bool)
|
||||||
|
if discoverDN {
|
||||||
|
cfg.DiscoverDN = discoverDN
|
||||||
|
}
|
||||||
|
|
||||||
|
caseSensitiveNames, ok := d.GetOk("case_sensitive_names")
|
||||||
|
if ok {
|
||||||
|
cfg.CaseSensitiveNames = new(bool)
|
||||||
|
*cfg.CaseSensitiveNames = caseSensitiveNames.(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
type ConfigEntry struct {
|
type ConfigEntry struct {
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
UserDN string `json:"userdn"`
|
UserDN string `json:"userdn"`
|
||||||
|
@ -34,6 +259,36 @@ type ConfigEntry struct {
|
||||||
CaseSensitiveNames *bool `json:"CaseSensitiveNames,omitempty"`
|
CaseSensitiveNames *bool `json:"CaseSensitiveNames,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ConfigEntry) Map() map[string]interface{} {
|
||||||
|
m := c.PasswordlessMap()
|
||||||
|
m["bindpass"] = c.BindPassword
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigEntry) PasswordlessMap() map[string]interface{} {
|
||||||
|
m := map[string]interface{}{
|
||||||
|
"url": c.Url,
|
||||||
|
"userdn": c.UserDN,
|
||||||
|
"groupdn": c.GroupDN,
|
||||||
|
"groupfilter": c.GroupFilter,
|
||||||
|
"groupattr": c.GroupAttr,
|
||||||
|
"upndomain": c.UPNDomain,
|
||||||
|
"userattr": c.UserAttr,
|
||||||
|
"certificate": c.Certificate,
|
||||||
|
"insecure_tls": c.InsecureTLS,
|
||||||
|
"starttls": c.StartTLS,
|
||||||
|
"binddn": c.BindDN,
|
||||||
|
"deny_null_bind": c.DenyNullBind,
|
||||||
|
"discoverdn": c.DiscoverDN,
|
||||||
|
"tls_min_version": c.TLSMinVersion,
|
||||||
|
"tls_max_version": c.TLSMaxVersion,
|
||||||
|
}
|
||||||
|
if c.CaseSensitiveNames != nil {
|
||||||
|
m["case_sensitive_names"] = *c.CaseSensitiveNames
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ConfigEntry) Validate() error {
|
func (c *ConfigEntry) Validate() error {
|
||||||
if len(c.Url) == 0 {
|
if len(c.Url) == 0 {
|
||||||
return errors.New("at least one url must be provided")
|
return errors.New("at least one url must be provided")
|
||||||
|
|
|
@ -138,7 +138,7 @@ func newEtcdV2Client(conf map[string]string) (client.Client, error) {
|
||||||
if (hasCert && hasKey) || hasCa {
|
if (hasCert && hasKey) || hasCa {
|
||||||
var transportErr error
|
var transportErr error
|
||||||
tls := transport.TLSInfo{
|
tls := transport.TLSInfo{
|
||||||
CAFile: ca,
|
TrustedCAFile: ca,
|
||||||
CertFile: cert,
|
CertFile: cert,
|
||||||
KeyFile: key,
|
KeyFile: key,
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ func newEtcd3Backend(conf map[string]string, logger log.Logger) (physical.Backen
|
||||||
ca, hasCa := conf["tls_ca_file"]
|
ca, hasCa := conf["tls_ca_file"]
|
||||||
if (hasCert && hasKey) || hasCa {
|
if (hasCert && hasKey) || hasCa {
|
||||||
tls := transport.TLSInfo{
|
tls := transport.TLSInfo{
|
||||||
CAFile: ca,
|
TrustedCAFile: ca,
|
||||||
CertFile: cert,
|
CertFile: cert,
|
||||||
KeyFile: key,
|
KeyFile: key,
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,12 @@ govendor init
|
||||||
echo "Fetching deps, will take some time..."
|
echo "Fetching deps, will take some time..."
|
||||||
govendor fetch +missing
|
govendor fetch +missing
|
||||||
|
|
||||||
|
# Clean up after the logrus mess
|
||||||
govendor remove github.com/Sirupsen/logrus
|
govendor remove github.com/Sirupsen/logrus
|
||||||
cd vendor
|
cd vendor
|
||||||
find -type f | grep '.go' | xargs sed -i -e 's/Sirupsen/sirupsen/'
|
find -type f | grep '.go' | xargs sed -i -e 's/Sirupsen/sirupsen/'
|
||||||
|
|
||||||
|
# Need the v2 branch for Azure
|
||||||
|
govendor fetch github.com/coreos/go-oidc@v2
|
||||||
|
|
||||||
echo "Done; to commit run \n\ncd ${GOPATH}/src/github.com/hashicorp/${TOOL}\n"
|
echo "Done; to commit run \n\ncd ${GOPATH}/src/github.com/hashicorp/${TOOL}\n"
|
||||||
|
|
|
@ -16,6 +16,7 @@ export default Ember.Component.extend({
|
||||||
class={{buttonClasses}}
|
class={{buttonClasses}}
|
||||||
type="button"
|
type="button"
|
||||||
disabled={{disabled}}
|
disabled={{disabled}}
|
||||||
|
data-test-confirm-action-trigger=true
|
||||||
{{action 'toggleConfirm'}}
|
{{action 'toggleConfirm'}}
|
||||||
>
|
>
|
||||||
{{yield}}
|
{{yield}}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
import Ember from 'ember';
|
||||||
|
const { assert, inject, Component } = Ember;
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
tagName: '',
|
||||||
|
flashMessages: inject.service(),
|
||||||
|
params: null,
|
||||||
|
successMessage() {
|
||||||
|
return 'Save was successful';
|
||||||
|
},
|
||||||
|
errorMessage() {
|
||||||
|
return 'There was an error saving';
|
||||||
|
},
|
||||||
|
onError(model) {
|
||||||
|
if (model && model.rollbackAttributes) {
|
||||||
|
model.rollbackAttributes();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSuccess(){},
|
||||||
|
// override and return a promise
|
||||||
|
transaction() {
|
||||||
|
assert('override transaction call in an extension of popup-base', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
performTransaction() {
|
||||||
|
let args = [...arguments];
|
||||||
|
let messageArgs = this.messageArgs(...args);
|
||||||
|
return this.transaction(...args)
|
||||||
|
.then(() => {
|
||||||
|
this.get('onSuccess')();
|
||||||
|
this.get('flashMessages').success(this.successMessage(...messageArgs));
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
this.onError(...messageArgs);
|
||||||
|
this.get('flashMessages').success(this.errorMessage(e, ...messageArgs));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
|
@ -2,20 +2,23 @@ import Ember from 'ember';
|
||||||
import { task } from 'ember-concurrency';
|
import { task } from 'ember-concurrency';
|
||||||
import { humanize } from 'vault/helpers/humanize';
|
import { humanize } from 'vault/helpers/humanize';
|
||||||
|
|
||||||
const { computed } = Ember;
|
const { computed, inject } = Ember;
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
|
flashMessages: inject.service(),
|
||||||
|
'data-test-component': 'identity-edit-form',
|
||||||
model: null,
|
model: null,
|
||||||
|
|
||||||
|
// 'create', 'edit', 'merge'
|
||||||
mode: 'create',
|
mode: 'create',
|
||||||
/*
|
/*
|
||||||
* @param Function
|
* @param Function
|
||||||
* @public
|
* @public
|
||||||
*
|
*
|
||||||
* Optional param to call a function upon successfully mounting a backend
|
* Optional param to call a function upon successfully saving an entity
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
onSave: () => {},
|
onSave: () => {},
|
||||||
|
|
||||||
cancelLink: computed('mode', 'model', function() {
|
cancelLink: computed('mode', 'model.identityType', function() {
|
||||||
let { model, mode } = this.getProperties('model', 'mode');
|
let { model, mode } = this.getProperties('model', 'mode');
|
||||||
let key = `${mode}-${model.get('identityType')}`;
|
let key = `${mode}-${model.get('identityType')}`;
|
||||||
let routes = {
|
let routes = {
|
||||||
|
@ -33,16 +36,17 @@ export default Ember.Component.extend({
|
||||||
return routes[key];
|
return routes[key];
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getMessage(model) {
|
getMessage(model, isDelete = false) {
|
||||||
let mode = this.get('mode');
|
let mode = this.get('mode');
|
||||||
let typeDisplay = humanize([model.get('identityType')]);
|
let typeDisplay = humanize([model.get('identityType')]);
|
||||||
|
let action = isDelete ? 'deleted' : 'saved';
|
||||||
if (mode === 'merge') {
|
if (mode === 'merge') {
|
||||||
return 'Successfully merged entities';
|
return 'Successfully merged entities';
|
||||||
}
|
}
|
||||||
if (model.get('id')) {
|
if (model.get('id')) {
|
||||||
return `Successfully saved ${typeDisplay} ${model.id}.`;
|
return `Successfully ${action} ${typeDisplay} ${model.id}.`;
|
||||||
}
|
}
|
||||||
return `Successfully saved ${typeDisplay}.`;
|
return `Successfully ${action} ${typeDisplay}.`;
|
||||||
},
|
},
|
||||||
|
|
||||||
save: task(function*() {
|
save: task(function*() {
|
||||||
|
@ -56,13 +60,26 @@ export default Ember.Component.extend({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.get('flashMessages').success(message);
|
this.get('flashMessages').success(message);
|
||||||
yield this.get('onSave')(model);
|
yield this.get('onSave')({saveType: 'save', model});
|
||||||
}).drop(),
|
}).drop(),
|
||||||
|
|
||||||
willDestroy() {
|
willDestroy() {
|
||||||
let model = this.get('model');
|
let model = this.get('model');
|
||||||
if (!model.isDestroyed || !model.isDestroying) {
|
if ((model.get('isDirty') && !model.isDestroyed) || !model.isDestroying) {
|
||||||
model.rollbackAttributes();
|
model.rollbackAttributes();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
deleteItem(model) {
|
||||||
|
let message = this.getMessage(model, true);
|
||||||
|
let flash = this.get('flashMessages');
|
||||||
|
model
|
||||||
|
.destroyRecord()
|
||||||
|
.then(() => {
|
||||||
|
flash.success(message);
|
||||||
|
return this.get('onSave')({saveType: 'delete', model});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
const { inject } = Ember;
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
flashMessages: inject.service(),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
enable(model) {
|
||||||
|
model.set('disabled', false);
|
||||||
|
|
||||||
|
model.save().
|
||||||
|
then(() => {
|
||||||
|
this.get('flashMessages').success(`Successfully enabled entity: ${model.id}`);
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
this.get('flashMessages').success(
|
||||||
|
`There was a problem enabling the entity: ${model.id} - ${e.error.join(' ') || e.message}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,22 @@
|
||||||
|
import Base from './_popup-base';
|
||||||
|
|
||||||
|
export default Base.extend({
|
||||||
|
messageArgs(model) {
|
||||||
|
let type = model.get('identityType');
|
||||||
|
let id = model.id;
|
||||||
|
return [type, id];
|
||||||
|
},
|
||||||
|
|
||||||
|
successMessage(type, id) {
|
||||||
|
return `Successfully deleted ${type}: ${id}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
errorMessage(e, type, id) {
|
||||||
|
let error = e.errors ? e.errors.join(' ') : e.message;
|
||||||
|
return `There was a problem deleting ${type}: ${id} - ${error}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
transaction(model) {
|
||||||
|
return model.destroyRecord();
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,34 @@
|
||||||
|
import Base from './_popup-base';
|
||||||
|
import Ember from 'ember';
|
||||||
|
const { computed } = Ember;
|
||||||
|
|
||||||
|
export default Base.extend({
|
||||||
|
model: computed.alias('params.firstObject'),
|
||||||
|
|
||||||
|
groupArray: computed('params', function() {
|
||||||
|
return this.get('params').objectAt(1);
|
||||||
|
}),
|
||||||
|
|
||||||
|
memberId: computed('params', function() {
|
||||||
|
return this.get('params').objectAt(2);
|
||||||
|
}),
|
||||||
|
|
||||||
|
messageArgs(/*model, groupArray, memberId*/) {
|
||||||
|
return [...arguments];
|
||||||
|
},
|
||||||
|
|
||||||
|
successMessage(model, groupArray, memberId) {
|
||||||
|
return `Successfully removed '${memberId}' from the group`;
|
||||||
|
},
|
||||||
|
|
||||||
|
errorMessage(e, model, groupArray, memberId) {
|
||||||
|
let error = e.errors ? e.errors.join(' ') : e.message;
|
||||||
|
return `There was a problem removing '${memberId}' from the group - ${error}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
transaction(model, groupArray, memberId) {
|
||||||
|
let members = model.get(groupArray);
|
||||||
|
model.set(groupArray, members.without(memberId));
|
||||||
|
return model.save();
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,29 @@
|
||||||
|
import Base from './_popup-base';
|
||||||
|
import Ember from 'ember';
|
||||||
|
const { computed } = Ember;
|
||||||
|
|
||||||
|
export default Base.extend({
|
||||||
|
model: computed.alias('params.firstObject'),
|
||||||
|
key: computed('params', function() {
|
||||||
|
return this.get('params').objectAt(1);
|
||||||
|
}),
|
||||||
|
|
||||||
|
messageArgs(model, key) {
|
||||||
|
return [model, key];
|
||||||
|
},
|
||||||
|
|
||||||
|
successMessage(model, key) {
|
||||||
|
return `Successfully removed '${key}' from metadata`;
|
||||||
|
},
|
||||||
|
errorMessage(e, model, key) {
|
||||||
|
let error = e.errors ? e.errors.join(' ') : e.message;
|
||||||
|
return `There was a problem removing '${key}' from the metadata - ${error}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
transaction(model, key) {
|
||||||
|
let metadata = model.get('metadata');
|
||||||
|
delete metadata[key];
|
||||||
|
model.set('metadata', { ...metadata });
|
||||||
|
return model.save();
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,29 @@
|
||||||
|
import Base from './_popup-base';
|
||||||
|
import Ember from 'ember';
|
||||||
|
const { computed } = Ember;
|
||||||
|
|
||||||
|
export default Base.extend({
|
||||||
|
model: computed.alias('params.firstObject'),
|
||||||
|
policyName: computed('params', function() {
|
||||||
|
return this.get('params').objectAt(1);
|
||||||
|
}),
|
||||||
|
|
||||||
|
messageArgs(model, policyName) {
|
||||||
|
return [model, policyName];
|
||||||
|
},
|
||||||
|
|
||||||
|
successMessage(model, policyName) {
|
||||||
|
return `Successfully removed '${policyName}' policy from ${model.id} `;
|
||||||
|
},
|
||||||
|
|
||||||
|
errorMessage(e, model, policyName) {
|
||||||
|
let error = e.errors ? e.errors.join(' ') : e.message;
|
||||||
|
return `There was a problem removing '${policyName}' policy - ${error}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
transaction(model, policyName) {
|
||||||
|
let policies = model.get('policies');
|
||||||
|
model.set('policies', policies.without(policyName));
|
||||||
|
return model.save();
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,6 +1,7 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
|
'data-test-component': 'info-table-row',
|
||||||
classNames: ['info-table-row'],
|
classNames: ['info-table-row'],
|
||||||
isVisible: Ember.computed.or('alwaysRender', 'value'),
|
isVisible: Ember.computed.or('alwaysRender', 'value'),
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ const { computed } = Ember;
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
type: null,
|
type: null,
|
||||||
|
|
||||||
|
yieldWithoutColumn: false,
|
||||||
|
|
||||||
classNameBindings: ['containerClass'],
|
classNameBindings: ['containerClass'],
|
||||||
|
|
||||||
containerClass: computed('type', function() {
|
containerClass: computed('type', function() {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
tagName: '',
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
tagName: '',
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
tagName: '',
|
||||||
|
});
|
|
@ -0,0 +1,6 @@
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
tagName: '',
|
||||||
|
hasLevel: true,
|
||||||
|
});
|
|
@ -0,0 +1,12 @@
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
tagName: '',
|
||||||
|
|
||||||
|
// api
|
||||||
|
isCertTab: false,
|
||||||
|
isConfigure: false,
|
||||||
|
baseKey: null,
|
||||||
|
backendCrumb: null,
|
||||||
|
model: null,
|
||||||
|
});
|
|
@ -71,10 +71,11 @@ export default Ember.Component.extend(DEFAULTS, {
|
||||||
|
|
||||||
handleSuccess(resp, action) {
|
handleSuccess(resp, action) {
|
||||||
let props = {};
|
let props = {};
|
||||||
if (resp && resp.data && action === 'unwrap') {
|
let secret = (resp && resp.data) || resp.auth;
|
||||||
props = Ember.assign({}, props, { unwrap_data: resp.data });
|
if (secret && action === 'unwrap') {
|
||||||
|
props = Ember.assign({}, props, { unwrap_data: secret });
|
||||||
}
|
}
|
||||||
props = Ember.assign({}, props, resp.data);
|
props = Ember.assign({}, props, secret);
|
||||||
|
|
||||||
if (resp && resp.wrap_info) {
|
if (resp && resp.wrap_info) {
|
||||||
const keyName = action === 'rewrap' ? 'rewrap_token' : 'token';
|
const keyName = action === 'rewrap' ? 'rewrap_token' : 'token';
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import ListController from 'vault/mixins/list-controller';
|
import ListController from 'vault/mixins/list-controller';
|
||||||
|
|
||||||
export default Ember.Controller.extend(ListController);
|
export default Ember.Controller.extend(ListController, {
|
||||||
|
actions: {
|
||||||
|
onDelete() {
|
||||||
|
this.send('reload');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
@ -4,7 +4,26 @@ import { task } from 'ember-concurrency';
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
showRoute: 'vault.cluster.access.identity.show',
|
showRoute: 'vault.cluster.access.identity.show',
|
||||||
showTab: 'details',
|
showTab: 'details',
|
||||||
navToShow: task(function*(model) {
|
navAfterSave: task(function*({saveType, model}) {
|
||||||
yield this.transitionToRoute(this.get('showRoute'), model.id, this.get('showTab'));
|
let isDelete = saveType === 'delete';
|
||||||
|
let type = model.get('identityType');
|
||||||
|
let listRoutes= {
|
||||||
|
'entity-alias': 'vault.cluster.access.identity.aliases.index',
|
||||||
|
'group-alias': 'vault.cluster.access.identity.aliases.index',
|
||||||
|
'group': 'vault.cluster.access.identity.index',
|
||||||
|
'entity': 'vault.cluster.access.identity.index',
|
||||||
|
};
|
||||||
|
let routeName = listRoutes[type]
|
||||||
|
if (!isDelete) {
|
||||||
|
yield this.transitionToRoute(
|
||||||
|
this.get('showRoute'),
|
||||||
|
model.id,
|
||||||
|
this.get('showTab')
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
yield this.transitionToRoute(
|
||||||
|
routeName
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,46 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import ListController from 'vault/mixins/list-controller';
|
import ListController from 'vault/mixins/list-controller';
|
||||||
|
|
||||||
export default Ember.Controller.extend(ListController);
|
const { inject } = Ember;
|
||||||
|
|
||||||
|
export default Ember.Controller.extend(ListController, {
|
||||||
|
flashMessages: inject.service(),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
delete(model) {
|
||||||
|
let type = model.get('identityType');
|
||||||
|
let id = model.id;
|
||||||
|
return model
|
||||||
|
.destroyRecord()
|
||||||
|
.then(() => {
|
||||||
|
this.send('reload');
|
||||||
|
this.get('flashMessages').success(`Successfully deleted ${type}: ${id}`);
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
this.get('flashMessages').success(
|
||||||
|
`There was a problem deleting ${type}: ${id} - ${e.error.join(' ') || e.message}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleDisabled(model) {
|
||||||
|
let action = model.get('disabled') ? ['enabled', 'enabling'] : ['disabled', 'disabling'];
|
||||||
|
let type = model.get('identityType');
|
||||||
|
let id = model.id;
|
||||||
|
model.toggleProperty('disabled');
|
||||||
|
|
||||||
|
model.save().
|
||||||
|
then(() => {
|
||||||
|
this.get('flashMessages').success(`Successfully ${action[0]} ${type}: ${id}`);
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
this.get('flashMessages').success(
|
||||||
|
`There was a problem ${action[1]} ${type}: ${id} - ${e.error.join(' ') || e.message}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
reloadRecord(model) {
|
||||||
|
model.reload();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import utils from 'vault/lib/key-utils';
|
import utils from 'vault/lib/key-utils';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
const { inject, computed, Controller } = Ember;
|
||||||
flashMessages: Ember.inject.service(),
|
export default Controller.extend({
|
||||||
clusterController: Ember.inject.controller('vault.cluster'),
|
flashMessages: inject.service(),
|
||||||
|
store: inject.service(),
|
||||||
|
clusterController: inject.controller('vault.cluster'),
|
||||||
queryParams: {
|
queryParams: {
|
||||||
page: 'page',
|
page: 'page',
|
||||||
pageFilter: 'pageFilter',
|
pageFilter: 'pageFilter',
|
||||||
|
@ -13,7 +15,7 @@ export default Ember.Controller.extend({
|
||||||
pageFilter: null,
|
pageFilter: null,
|
||||||
filter: null,
|
filter: null,
|
||||||
|
|
||||||
backendCrumb: Ember.computed(function() {
|
backendCrumb: computed(function() {
|
||||||
return {
|
return {
|
||||||
label: 'leases',
|
label: 'leases',
|
||||||
text: 'leases',
|
text: 'leases',
|
||||||
|
@ -24,13 +26,13 @@ export default Ember.Controller.extend({
|
||||||
|
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
|
||||||
filterMatchesKey: Ember.computed('filter', 'model', 'model.[]', function() {
|
filterMatchesKey: computed('filter', 'model', 'model.[]', function() {
|
||||||
var filter = this.get('filter');
|
var filter = this.get('filter');
|
||||||
var content = this.get('model');
|
var content = this.get('model');
|
||||||
return !!(content.length && content.findBy('id', filter));
|
return !!(content.length && content.findBy('id', filter));
|
||||||
}),
|
}),
|
||||||
|
|
||||||
firstPartialMatch: Ember.computed('filter', 'model', 'model.[]', 'filterMatchesKey', function() {
|
firstPartialMatch: computed('filter', 'model', 'model.[]', 'filterMatchesKey', function() {
|
||||||
var filter = this.get('filter');
|
var filter = this.get('filter');
|
||||||
var content = this.get('model');
|
var content = this.get('model');
|
||||||
var filterMatchesKey = this.get('filterMatchesKey');
|
var filterMatchesKey = this.get('filterMatchesKey');
|
||||||
|
@ -42,7 +44,7 @@ export default Ember.Controller.extend({
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
filterIsFolder: Ember.computed('filter', function() {
|
filterIsFolder: computed('filter', function() {
|
||||||
return !!utils.keyIsFolder(this.get('filter'));
|
return !!utils.keyIsFolder(this.get('filter'));
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -56,7 +58,7 @@ export default Ember.Controller.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
revokePrefix(prefix, isForce) {
|
revokePrefix(prefix, isForce) {
|
||||||
const adapter = this.model.store.adapterFor('lease');
|
const adapter = this.get('store').adapterFor('lease');
|
||||||
const method = isForce ? 'forceRevokePrefix' : 'revokePrefix';
|
const method = isForce ? 'forceRevokePrefix' : 'revokePrefix';
|
||||||
const fn = adapter[method];
|
const fn = adapter[method];
|
||||||
fn
|
fn
|
||||||
|
|
|
@ -66,6 +66,7 @@ export default Ember.Controller.extend(BackendCrumbMixin, {
|
||||||
delete(item) {
|
delete(item) {
|
||||||
const name = item.id;
|
const name = item.id;
|
||||||
item.destroyRecord().then(() => {
|
item.destroyRecord().then(() => {
|
||||||
|
this.send('reload');
|
||||||
this.get('flashMessages').success(`${name} was successfully deleted.`);
|
this.get('flashMessages').success(`${name} was successfully deleted.`);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -30,7 +30,6 @@ export default Ember.Controller.extend({
|
||||||
description: null,
|
description: null,
|
||||||
default_lease_ttl: null,
|
default_lease_ttl: null,
|
||||||
max_lease_ttl: null,
|
max_lease_ttl: null,
|
||||||
force_no_cache: null,
|
|
||||||
showConfig: false,
|
showConfig: false,
|
||||||
local: false,
|
local: false,
|
||||||
sealWrap: false,
|
sealWrap: false,
|
||||||
|
@ -50,7 +49,6 @@ export default Ember.Controller.extend({
|
||||||
description: null,
|
description: null,
|
||||||
default_lease_ttl: null,
|
default_lease_ttl: null,
|
||||||
max_lease_ttl: null,
|
max_lease_ttl: null,
|
||||||
force_no_cache: null,
|
|
||||||
local: false,
|
local: false,
|
||||||
showConfig: false,
|
showConfig: false,
|
||||||
sealWrap: false,
|
sealWrap: false,
|
||||||
|
@ -82,7 +80,6 @@ export default Ember.Controller.extend({
|
||||||
selectedType: type,
|
selectedType: type,
|
||||||
description,
|
description,
|
||||||
default_lease_ttl,
|
default_lease_ttl,
|
||||||
force_no_cache,
|
|
||||||
local,
|
local,
|
||||||
max_lease_ttl,
|
max_lease_ttl,
|
||||||
sealWrap,
|
sealWrap,
|
||||||
|
@ -92,7 +89,6 @@ export default Ember.Controller.extend({
|
||||||
'selectedType',
|
'selectedType',
|
||||||
'description',
|
'description',
|
||||||
'default_lease_ttl',
|
'default_lease_ttl',
|
||||||
'force_no_cache',
|
|
||||||
'local',
|
'local',
|
||||||
'max_lease_ttl',
|
'max_lease_ttl',
|
||||||
'sealWrap',
|
'sealWrap',
|
||||||
|
@ -112,9 +108,8 @@ export default Ember.Controller.extend({
|
||||||
|
|
||||||
if (this.get('showConfig')) {
|
if (this.get('showConfig')) {
|
||||||
attrs.config = {
|
attrs.config = {
|
||||||
default_lease_ttl,
|
defaultLeaseTtl: default_lease_ttl,
|
||||||
max_lease_ttl,
|
maxLeaseTtl: max_lease_ttl,
|
||||||
force_no_cache,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
|
||||||
|
|
||||||
|
export default function() {
|
||||||
|
return lazyCapabilities(apiPath`identity/${'identityType'}/id/${'id'}`, 'id', 'identityType');
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { queryRecord } from 'ember-computed-query';
|
||||||
|
|
||||||
|
export function apiPath(strings, ...keys) {
|
||||||
|
return function(data) {
|
||||||
|
let dict = data || {};
|
||||||
|
let result = [strings[0]];
|
||||||
|
keys.forEach((key, i) => {
|
||||||
|
result.push(dict[key], strings[i + 1]);
|
||||||
|
});
|
||||||
|
return result.join('');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function() {
|
||||||
|
let [templateFn, ...keys] = arguments;
|
||||||
|
return queryRecord(
|
||||||
|
'capabilities',
|
||||||
|
context => {
|
||||||
|
return {
|
||||||
|
id: templateFn(context.getProperties(...keys)),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
...keys
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,8 +1,12 @@
|
||||||
import IdentityModel from './_base';
|
import IdentityModel from './_base';
|
||||||
import DS from 'ember-data';
|
import DS from 'ember-data';
|
||||||
|
import Ember from 'ember';
|
||||||
|
import identityCapabilities from 'vault/macros/identity-capabilities';
|
||||||
const { attr, belongsTo } = DS;
|
const { attr, belongsTo } = DS;
|
||||||
|
const { computed } = Ember;
|
||||||
|
|
||||||
export default IdentityModel.extend({
|
export default IdentityModel.extend({
|
||||||
|
parentType: 'entity',
|
||||||
formFields: ['name', 'mountAccessor', 'metadata'],
|
formFields: ['name', 'mountAccessor', 'metadata'],
|
||||||
entity: belongsTo('identity/entity', { readOnly: true, async: false }),
|
entity: belongsTo('identity/entity', { readOnly: true, async: false }),
|
||||||
|
|
||||||
|
@ -12,7 +16,7 @@ export default IdentityModel.extend({
|
||||||
label: 'Auth Backend',
|
label: 'Auth Backend',
|
||||||
editType: 'mountAccessor',
|
editType: 'mountAccessor',
|
||||||
}),
|
}),
|
||||||
metadata: attr('object', {
|
metadata: attr({
|
||||||
editType: 'kv',
|
editType: 'kv',
|
||||||
}),
|
}),
|
||||||
mountPath: attr('string', {
|
mountPath: attr('string', {
|
||||||
|
@ -28,4 +32,8 @@ export default IdentityModel.extend({
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
}),
|
}),
|
||||||
mergedFromCanonicalIds: attr(),
|
mergedFromCanonicalIds: attr(),
|
||||||
|
|
||||||
|
updatePath: identityCapabilities(),
|
||||||
|
canDelete: computed.alias('updatePath.canDelete'),
|
||||||
|
canEdit: computed.alias('updatePath.canUpdate'),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
|
import Ember from 'ember';
|
||||||
import IdentityModel from './_base';
|
import IdentityModel from './_base';
|
||||||
import DS from 'ember-data';
|
import DS from 'ember-data';
|
||||||
|
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
|
||||||
|
import identityCapabilities from 'vault/macros/identity-capabilities';
|
||||||
|
|
||||||
|
const { computed } = Ember;
|
||||||
|
|
||||||
const { attr, hasMany } = DS;
|
const { attr, hasMany } = DS;
|
||||||
|
|
||||||
export default IdentityModel.extend({
|
export default IdentityModel.extend({
|
||||||
formFields: ['name', 'policies', 'metadata'],
|
formFields: ['name', 'disabled', 'policies', 'metadata'],
|
||||||
name: attr('string'),
|
name: attr('string'),
|
||||||
|
disabled: attr('boolean', {
|
||||||
|
defaultValue: false,
|
||||||
|
label: 'Disable entity',
|
||||||
|
helpText: 'All associated tokens cannot be used, but are not revoked.',
|
||||||
|
}),
|
||||||
mergedEntityIds: attr(),
|
mergedEntityIds: attr(),
|
||||||
metadata: attr('object', {
|
metadata: attr({
|
||||||
editType: 'kv',
|
editType: 'kv',
|
||||||
}),
|
}),
|
||||||
policies: attr({
|
policies: attr({
|
||||||
|
@ -28,4 +39,11 @@ export default IdentityModel.extend({
|
||||||
inheritedGroupIds: attr({
|
inheritedGroupIds: attr({
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
updatePath: identityCapabilities(),
|
||||||
|
canDelete: computed.alias('updatePath.canDelete'),
|
||||||
|
canEdit: computed.alias('updatePath.canUpdate'),
|
||||||
|
|
||||||
|
aliasPath: lazyCapabilities(apiPath`identity/entity-alias`),
|
||||||
|
canAddAlias: computed.alias('aliasPath.canCreate'),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
import IdentityModel from './_base';
|
import IdentityModel from './_base';
|
||||||
import DS from 'ember-data';
|
import DS from 'ember-data';
|
||||||
|
import Ember from 'ember';
|
||||||
|
import identityCapabilities from 'vault/macros/identity-capabilities';
|
||||||
|
|
||||||
const { attr, belongsTo } = DS;
|
const { attr, belongsTo } = DS;
|
||||||
|
const { computed } = Ember;
|
||||||
|
|
||||||
export default IdentityModel.extend({
|
export default IdentityModel.extend({
|
||||||
|
parentType: 'group',
|
||||||
formFields: ['name', 'mountAccessor'],
|
formFields: ['name', 'mountAccessor'],
|
||||||
group: belongsTo('identity/group', { readOnly: true, async: false }),
|
group: belongsTo('identity/group', { readOnly: true, async: false }),
|
||||||
|
|
||||||
|
@ -26,4 +31,9 @@ export default IdentityModel.extend({
|
||||||
lastUpdateTime: attr('string', {
|
lastUpdateTime: attr('string', {
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
updatePath: identityCapabilities(),
|
||||||
|
canDelete: computed.alias('updatePath.canDelete'),
|
||||||
|
canEdit: computed.alias('updatePath.canUpdate'),
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import IdentityModel from './_base';
|
import IdentityModel from './_base';
|
||||||
import DS from 'ember-data';
|
import DS from 'ember-data';
|
||||||
|
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
|
||||||
|
import identityCapabilities from 'vault/macros/identity-capabilities';
|
||||||
|
|
||||||
const { computed } = Ember;
|
const { computed } = Ember;
|
||||||
const { attr, belongsTo } = DS;
|
const { attr, belongsTo } = DS;
|
||||||
|
@ -52,4 +54,18 @@ export default IdentityModel.extend({
|
||||||
),
|
),
|
||||||
|
|
||||||
alias: belongsTo('identity/group-alias', { async: false, readOnly: true }),
|
alias: belongsTo('identity/group-alias', { async: false, readOnly: true }),
|
||||||
|
updatePath: identityCapabilities(),
|
||||||
|
canDelete: computed.alias('updatePath.canDelete'),
|
||||||
|
canEdit: computed.alias('updatePath.canUpdate'),
|
||||||
|
|
||||||
|
aliasPath: lazyCapabilities(apiPath`identity/group-alias`),
|
||||||
|
canAddAlias: computed('aliasPath.canCreate', 'type', 'alias', function() {
|
||||||
|
let type = this.get('type');
|
||||||
|
let alias = this.get('alias');
|
||||||
|
// internal groups can't have aliases, and external groups can only have one
|
||||||
|
if (type === 'internal' || alias) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.get('aliasPath.canCreate');
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,5 +2,7 @@ import attr from 'ember-data/attr';
|
||||||
import Fragment from 'ember-data-model-fragments/fragment';
|
import Fragment from 'ember-data-model-fragments/fragment';
|
||||||
|
|
||||||
export default Fragment.extend({
|
export default Fragment.extend({
|
||||||
version: attr('number'),
|
version: attr('number', {
|
||||||
|
label: 'Version',
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,6 +3,8 @@ import DS from 'ember-data';
|
||||||
import { queryRecord } from 'ember-computed-query';
|
import { queryRecord } from 'ember-computed-query';
|
||||||
import { fragment } from 'ember-data-model-fragments/attributes';
|
import { fragment } from 'ember-data-model-fragments/attributes';
|
||||||
|
|
||||||
|
import { expandAttributeMeta } from 'vault/utils/field-to-attrs';
|
||||||
|
|
||||||
const { attr } = DS;
|
const { attr } = DS;
|
||||||
const { computed } = Ember;
|
const { computed } = Ember;
|
||||||
|
|
||||||
|
@ -16,11 +18,26 @@ export default DS.Model.extend({
|
||||||
name: attr('string'),
|
name: attr('string'),
|
||||||
type: attr('string'),
|
type: attr('string'),
|
||||||
description: attr('string'),
|
description: attr('string'),
|
||||||
config: attr('object'),
|
config: fragment('mount-config', { defaultValue: {} }),
|
||||||
options: fragment('mount-options'),
|
options: fragment('mount-options', { defaultValue: {} }),
|
||||||
local: attr('boolean'),
|
local: attr('boolean'),
|
||||||
sealWrap: attr('boolean'),
|
sealWrap: attr('boolean'),
|
||||||
|
|
||||||
|
formFields: [
|
||||||
|
'type',
|
||||||
|
'path',
|
||||||
|
'description',
|
||||||
|
'accessor',
|
||||||
|
'local',
|
||||||
|
'sealWrap',
|
||||||
|
'config.{defaultLeaseTtl,maxLeaseTtl}',
|
||||||
|
'options.{version}',
|
||||||
|
],
|
||||||
|
|
||||||
|
attrs: computed('formFields', function() {
|
||||||
|
return expandAttributeMeta(this, this.get('formFields'));
|
||||||
|
}),
|
||||||
|
|
||||||
shouldIncludeInList: computed('type', function() {
|
shouldIncludeInList: computed('type', function() {
|
||||||
return !LIST_EXCLUDED_BACKENDS.includes(this.get('type'));
|
return !LIST_EXCLUDED_BACKENDS.includes(this.get('type'));
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -68,6 +68,7 @@ Router.map(function() {
|
||||||
this.route('backends', { path: '/' });
|
this.route('backends', { path: '/' });
|
||||||
this.route('backend', { path: '/:backend' }, function() {
|
this.route('backend', { path: '/:backend' }, function() {
|
||||||
this.route('index', { path: '/' });
|
this.route('index', { path: '/' });
|
||||||
|
this.route('configuration');
|
||||||
// because globs / params can't be empty,
|
// because globs / params can't be empty,
|
||||||
// we have to special-case ids of '' with thier own routes
|
// we have to special-case ids of '' with thier own routes
|
||||||
this.route('list-root', { path: '/list/' });
|
this.route('list-root', { path: '/list/' });
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
import UnloadModelRoute from 'vault/mixins/unload-model-route';
|
||||||
|
import UnsavedModelRoute from 'vault/mixins/unsaved-model-route';
|
||||||
|
|
||||||
export default Ember.Route.extend({
|
export default Ember.Route.extend(UnloadModelRoute, UnsavedModelRoute, {
|
||||||
model(params) {
|
model(params) {
|
||||||
let itemType = this.modelFor('vault.cluster.access.identity');
|
let itemType = this.modelFor('vault.cluster.access.identity');
|
||||||
let modelType = `identity/${itemType}-alias`;
|
let modelType = `identity/${itemType}-alias`;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
import UnloadModelRoute from 'vault/mixins/unload-model-route';
|
||||||
|
import UnsavedModelRoute from 'vault/mixins/unsaved-model-route';
|
||||||
|
|
||||||
export default Ember.Route.extend({
|
export default Ember.Route.extend(UnloadModelRoute, UnsavedModelRoute, {
|
||||||
model(params) {
|
model(params) {
|
||||||
let itemType = this.modelFor('vault.cluster.access.identity');
|
let itemType = this.modelFor('vault.cluster.access.identity');
|
||||||
let modelType = `identity/${itemType}-alias`;
|
let modelType = `identity/${itemType}-alias`;
|
||||||
|
|
|
@ -27,10 +27,14 @@ export default Ember.Route.extend(ListRoute, {
|
||||||
actions: {
|
actions: {
|
||||||
willTransition(transition) {
|
willTransition(transition) {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
if (transition.targetName !== this.routeName) {
|
if (!transition || transition.targetName !== this.routeName) {
|
||||||
this.store.clearAllDatasets();
|
this.store.clearAllDatasets();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
reload() {
|
||||||
|
this.store.clearAllDatasets();
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
import UnloadModelRoute from 'vault/mixins/unload-model-route';
|
||||||
|
import UnsavedModelRoute from 'vault/mixins/unsaved-model-route';
|
||||||
|
|
||||||
export default Ember.Route.extend({
|
export default Ember.Route.extend(UnloadModelRoute, UnsavedModelRoute, {
|
||||||
model() {
|
model() {
|
||||||
let itemType = this.modelFor('vault.cluster.access.identity');
|
let itemType = this.modelFor('vault.cluster.access.identity');
|
||||||
let modelType = `identity/${itemType}`;
|
let modelType = `identity/${itemType}`;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
import UnloadModelRoute from 'vault/mixins/unload-model-route';
|
||||||
|
import UnsavedModelRoute from 'vault/mixins/unsaved-model-route';
|
||||||
|
|
||||||
export default Ember.Route.extend({
|
export default Ember.Route.extend(UnloadModelRoute, UnsavedModelRoute, {
|
||||||
model(params) {
|
model(params) {
|
||||||
let itemType = this.modelFor('vault.cluster.access.identity');
|
let itemType = this.modelFor('vault.cluster.access.identity');
|
||||||
let modelType = `identity/${itemType}`;
|
let modelType = `identity/${itemType}`;
|
||||||
|
|
|
@ -34,5 +34,9 @@ export default Ember.Route.extend(ListRoute, {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
reload() {
|
||||||
|
this.store.clearAllDatasets();
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,13 +13,36 @@ export default Ember.Route.extend({
|
||||||
Ember.set(error, 'httpStatus', 404);
|
Ember.set(error, 'httpStatus', 404);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
// TODO peekRecord here to see if we have the record already
|
|
||||||
|
// if the record is in the store use that
|
||||||
|
let model = this.store.peekRecord(modelType, params.item_id);
|
||||||
|
|
||||||
|
// if we don't have creationTime, we only have a partial model so reload
|
||||||
|
if (model && !model.get('creationTime')) {
|
||||||
|
model = model.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there's no model, we need to fetch it
|
||||||
|
if (!model) {
|
||||||
|
model = this.store.findRecord(modelType, params.item_id);
|
||||||
|
}
|
||||||
|
|
||||||
return Ember.RSVP.hash({
|
return Ember.RSVP.hash({
|
||||||
model: this.store.findRecord(modelType, params.item_id),
|
model,
|
||||||
section,
|
section,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
// if we're just entering the route, and it's not a hard reload
|
||||||
|
// reload to make sure we have the newest info
|
||||||
|
if (this.currentModel) {
|
||||||
|
Ember.run.next(() => {
|
||||||
|
this.controller.get('model').reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
afterModel(resolvedModel) {
|
afterModel(resolvedModel) {
|
||||||
let { section, model } = resolvedModel;
|
let { section, model } = resolvedModel;
|
||||||
if (model.get('identityType') === 'group' && model.get('type') === 'internal' && section === 'aliases') {
|
if (model.get('identityType') === 'group' && model.get('type') === 'internal' && section === 'aliases') {
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Route.extend({
|
||||||
|
model() {
|
||||||
|
return this.modelFor('vault.cluster.secrets.backend');
|
||||||
|
},
|
||||||
|
});
|
|
@ -159,5 +159,9 @@ export default Ember.Route.extend({
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
reload() {
|
||||||
|
this.refresh();
|
||||||
|
this.store.clearAllDatasets();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -131,13 +131,25 @@ export default DS.Store.extend({
|
||||||
// pushes records into the store and returns the result
|
// pushes records into the store and returns the result
|
||||||
fetchPage(modelName, query) {
|
fetchPage(modelName, query) {
|
||||||
const response = this.constructResponse(modelName, query);
|
const response = this.constructResponse(modelName, query);
|
||||||
this.unloadAll(modelName);
|
this.peekAll(modelName).forEach(record => {
|
||||||
|
record.unloadRecord();
|
||||||
|
});
|
||||||
|
return new Ember.RSVP.Promise(resolve => {
|
||||||
|
Ember.run.schedule('destroy', () => {
|
||||||
this.push(
|
this.push(
|
||||||
this.serializerFor(modelName).normalizeResponse(this, this.modelFor(modelName), response, null, 'query')
|
this.serializerFor(modelName).normalizeResponse(
|
||||||
|
this,
|
||||||
|
this.modelFor(modelName),
|
||||||
|
response,
|
||||||
|
null,
|
||||||
|
'query'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
const model = this.peekAll(modelName);
|
let model = this.peekAll(modelName).toArray();
|
||||||
model.set('meta', response.meta);
|
model.set('meta', response.meta);
|
||||||
return model;
|
resolve(model);
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// get cached data
|
// get cached data
|
||||||
|
|
|
@ -20,8 +20,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.popup-menu-trigger {
|
.popup-menu-trigger {
|
||||||
width: 3rem;
|
min-width: auto;
|
||||||
height: 2rem;
|
|
||||||
}
|
}
|
||||||
.popup-menu-trigger.is-active {
|
.popup-menu-trigger.is-active {
|
||||||
&,
|
&,
|
||||||
|
@ -50,6 +49,7 @@
|
||||||
height: auto;
|
height: auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $menu-item-hover-background-color;
|
background-color: $menu-item-hover-background-color;
|
||||||
|
|
|
@ -133,6 +133,17 @@ $button-box-shadow-standard: 0 3px 1px 0 rgba($black, 0.12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-orange {
|
||||||
|
background-color: $orange;
|
||||||
|
border-color: $orange;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&.is-hovered {
|
||||||
|
background-color: darken($orange, 5%);
|
||||||
|
border-color: darken($orange, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
&.is-compact {
|
&.is-compact {
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
padding: $size-11 $size-8;
|
padding: $size-11 $size-8;
|
||||||
|
@ -146,7 +157,6 @@ $button-box-shadow-standard: 0 3px 1px 0 rgba($black, 0.12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-more-icon,
|
|
||||||
&.tool-tip-trigger {
|
&.tool-tip-trigger {
|
||||||
color: $black;
|
color: $black;
|
||||||
min-width: auto;
|
min-width: auto;
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if (is-active-route (array 'vault.cluster.policies' 'vault.cluster.policy')) 'is-active'}}">
|
<li class="{{if (is-active-route (array 'vault.cluster.policies' 'vault.cluster.policy')) 'is-active'}}">
|
||||||
<a href="{{href-to "vault.cluster.policies" activeClusterName current-when='vault.cluster.policies vault.cluster.policy'}}">
|
<a href="{{href-to "vault.cluster.policies" "acl" current-when='vault.cluster.policies vault.cluster.policy'}}">
|
||||||
Policies
|
Policies
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
{{form-field data-test-field attr=attr model=model}}
|
{{form-field data-test-field attr=attr model=model}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
<div class="field is-grouped box is-fullwidth is-bottomless">
|
|
||||||
|
<div class="field is-grouped is-grouped-split is-fullwidth box is-bottomless">
|
||||||
|
<div class="field is-grouped">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<button type="submit" data-test-identity-submit=true class="button is-primary {{if save.isRunning 'loading'}}" disabled={{save.isRunning}}>
|
<button type="submit" data-test-identity-submit=true class="button is-primary {{if save.isRunning 'loading'}}" disabled={{save.isRunning}}>
|
||||||
{{#if (eq mode "create")}}
|
{{#if (eq mode "create")}}
|
||||||
|
@ -20,14 +22,27 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</button>
|
</button>
|
||||||
{{#if (or (eq mode "merge") (eq mode "create" ))}}
|
{{#if (or (eq mode "merge") (eq mode "create" ))}}
|
||||||
<a href={{href-to cancelLink}} class="button">
|
<a href={{href-to cancelLink}} class="button" data-test-cancel-link>
|
||||||
Cancel
|
Cancel
|
||||||
</a>
|
</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a href={{href-to cancelLink model.id "details"}} class="button">
|
<a href={{href-to cancelLink model.id "details"}} class="button" data-test-cancel-link>
|
||||||
Cancel
|
Cancel
|
||||||
</a>
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{#if (and (eq mode "edit") model.canDelete)}}
|
||||||
|
{{#confirm-action
|
||||||
|
buttonClasses="button is-ghost"
|
||||||
|
onConfirmAction=(action "deleteItem" model)
|
||||||
|
confirmMessage=(concat "Are you sure you want to delete " model.id "?")
|
||||||
|
data-test-entity-item-delete=true
|
||||||
|
}}
|
||||||
|
Delete
|
||||||
|
{{/confirm-action}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="level-right">
|
<div class="level-right">
|
||||||
{{#if (eq identityType "entity")}}
|
{{#if (eq identityType "entity")}}
|
||||||
<a href="{{href-to 'vault.cluster.access.identity.merge'}}" class="button has-icon-right is-ghost is-compact" data-test-entity-merge-link=true>
|
<a href="{{href-to 'vault.cluster.access.identity.merge' (pluralize identityType)}}" class="button has-icon-right is-ghost is-compact" data-test-entity-merge-link=true>
|
||||||
Merge {{pluralize identityType}}
|
Merge {{pluralize identityType}}
|
||||||
{{i-con glyph="chevron-right" size=11}}
|
{{i-con glyph="chevron-right" size=11}}
|
||||||
</a>
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<a href="{{href-to 'vault.cluster.access.identity.create'}}" class="button has-icon-right is-ghost is-compact" data-test-entity-create-link=true>
|
<a href="{{href-to 'vault.cluster.access.identity.create' (pluralize identityType)}}" class="button has-icon-right is-ghost is-compact" data-test-entity-create-link=true>
|
||||||
Create {{identityType}}
|
Create {{identityType}}
|
||||||
{{i-con glyph="chevron-right" size=11}}
|
{{i-con glyph="chevron-right" size=11}}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{info-table-row label="Name" value=model.name }}
|
{{info-table-row label="Name" value=model.name data-test-alias-name=true}}
|
||||||
{{info-table-row label="ID" value=model.id }}
|
{{info-table-row label="ID" value=model.id }}
|
||||||
{{#info-table-row label=(if (eq model.identityType "entity-alias") "Entity ID" "Group ID") value=model.canonicalId}}
|
{{#info-table-row label=(if (eq model.identityType "entity-alias") "Entity ID" "Group ID") value=model.canonicalId}}
|
||||||
<a href={{href-to 'vault.cluster.access.identity.show' (if (eq model.identityType "entity-alias") "entities" "groups") model.canonicalId "details"}}
|
<a href={{href-to 'vault.cluster.access.identity.show' (if (eq model.identityType "entity-alias") "entities" "groups") model.canonicalId "details"}}
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
{{value}}
|
{{value}}
|
||||||
</div>
|
</div>
|
||||||
<div class="column has-text-right">
|
<div class="column has-text-right">
|
||||||
|
{{#if model.canEdit}}
|
||||||
|
{{identity/popup-metadata params=(array model key)}}
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
<code class="has-text-grey is-size-8">{{item.mountAccessor}}</code>
|
<code class="has-text-grey is-size-8">{{item.mountAccessor}}</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="column has-text-right">
|
<div class="column has-text-right">
|
||||||
|
{{identity/popup-alias params=(array item)}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/linked-block}}
|
{{/linked-block}}
|
||||||
|
|
|
@ -1,4 +1,20 @@
|
||||||
{{info-table-row label="Name" value=model.name }}
|
{{#if model.disabled}}
|
||||||
|
<div class="box is-shadowless is-marginless">
|
||||||
|
{{#message-in-page type="warning" yieldWithoutColumn=true messageClass="message-body is-marginless" data-test-disabled-warning=true}}
|
||||||
|
<div class="column">
|
||||||
|
<strong>Attention</strong> This {{model.identityType}} is disabled. All associated tokens cannot be used, but are not revoked.
|
||||||
|
</div>
|
||||||
|
{{#if model.canEdit}}
|
||||||
|
<div class="column is-flex-v-centered is-narrow">
|
||||||
|
<button type="button" class="button is-orange box" {{action "enable" model}} data-test-enable=true>
|
||||||
|
Enable
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{/message-in-page}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{info-table-row label="Name" value=model.name data-test-identity-item-name=true}}
|
||||||
{{info-table-row label="Type" value=model.type }}
|
{{info-table-row label="Type" value=model.type }}
|
||||||
{{info-table-row label="ID" value=model.id }}
|
{{info-table-row label="ID" value=model.id }}
|
||||||
{{#info-table-row label="Merged Ids" value=model.mergedEntityIds }}
|
{{#info-table-row label="Merged Ids" value=model.mergedEntityIds }}
|
||||||
|
|
|
@ -1,21 +1,56 @@
|
||||||
{{#if model.hasMembers}}
|
{{#if model.hasMembers}}
|
||||||
{{#each model.memberGroupIds as |gid|}}
|
{{#each model.memberGroupIds as |gid|}}
|
||||||
<a href={{href-to "vault.cluster.access.identity.show" "groups" gid "details" }}
|
|
||||||
|
{{#linked-block
|
||||||
|
"vault.cluster.access.identity.show"
|
||||||
|
"groups"
|
||||||
|
gid
|
||||||
|
details
|
||||||
class="box is-sideless is-marginless"
|
class="box is-sideless is-marginless"
|
||||||
|
}}
|
||||||
|
<div class="columns is-mobile">
|
||||||
|
<div class="column is-10">
|
||||||
|
<a href={{href-to "vault.cluster.access.identity.show" "groups" gid "details" }}
|
||||||
|
class="is-block has-text-black has-text-weight-semibold"
|
||||||
>{{i-con
|
>{{i-con
|
||||||
glyph='folder'
|
glyph='folder'
|
||||||
size=14
|
size=14
|
||||||
class="has-text-grey-light"
|
class="has-text-grey-light"
|
||||||
}}{{gid}}</a>
|
}}{{gid}}</a>
|
||||||
|
</div>
|
||||||
|
<div class="column has-text-right">
|
||||||
|
{{#if model.canEdit}}
|
||||||
|
{{identity/popup-members params=(array model "memberGroupIds" gid)}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/linked-block}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{#each model.memberEntityIds as |gid|}}
|
{{#each model.memberEntityIds as |gid|}}
|
||||||
<a href={{href-to "vault.cluster.access.identity.show" "entities" gid "details" }}
|
{{#linked-block
|
||||||
|
"vault.cluster.access.identity.show"
|
||||||
|
"groups"
|
||||||
|
gid
|
||||||
|
details
|
||||||
class="box is-sideless is-marginless"
|
class="box is-sideless is-marginless"
|
||||||
|
}}
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column is-10">
|
||||||
|
<a href={{href-to "vault.cluster.access.identity.show" "entities" gid "details" }}
|
||||||
|
class="is-block has-text-black has-text-weight-semibold"
|
||||||
>{{i-con
|
>{{i-con
|
||||||
glyph='role'
|
glyph='role'
|
||||||
size=14
|
size=14
|
||||||
class="has-text-grey-light"
|
class="has-text-grey-light"
|
||||||
}}{{gid}}</a>
|
}}{{gid}}</a>
|
||||||
|
</div>
|
||||||
|
<div class="column has-text-right">
|
||||||
|
{{#if model.canEdit}}
|
||||||
|
{{identity/popup-members params=(array model "memberEntityIds" gid)}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/linked-block}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="box is-bottomless has-background-white-bis">
|
<div class="box is-bottomless has-background-white-bis">
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
{{value}}
|
{{value}}
|
||||||
</div>
|
</div>
|
||||||
<div class="column has-text-right">
|
<div class="column has-text-right">
|
||||||
|
{{#if model.canEdit}}
|
||||||
|
{{identity/popup-metadata params=(array model key)}}
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{#each model.policies as |item|}}
|
{{#each model.policies as |policyName|}}
|
||||||
{{#linked-block
|
{{#linked-block
|
||||||
"vault.cluster.policy.show"
|
"vault.cluster.policy.show"
|
||||||
"acl"
|
"acl"
|
||||||
|
@ -7,12 +7,15 @@
|
||||||
}}
|
}}
|
||||||
<div class="columns is-mobile">
|
<div class="columns is-mobile">
|
||||||
<div class="column is-10">
|
<div class="column is-10">
|
||||||
<a href={{href-to "vault.cluster.policy.show" "acl" item}}
|
<a href={{href-to "vault.cluster.policy.show" "acl" policyName}}
|
||||||
class="has-text-black has-text-weight-semibold"
|
class="is-block has-text-black has-text-weight-semibold"
|
||||||
><span class="is-underline">{{item}}</span>
|
><span class="is-underline">{{policyName}}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="column has-text-right">
|
<div class="column has-text-right">
|
||||||
|
{{#if model.canEdit}}
|
||||||
|
{{identity/popup-policy params=(array model policyName)}}
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/linked-block}}
|
{{/linked-block}}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
{{#popup-menu name="alias-menu"}}
|
||||||
|
{{#with params.firstObject as |item|}}
|
||||||
|
<nav class="menu">
|
||||||
|
<ul class="menu-list">
|
||||||
|
<li class="action">
|
||||||
|
<a href={{href-to "vault.cluster.access.identity.aliases.show" (pluralize item.parentType) item.id "details" }}>
|
||||||
|
Details
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{{#if item.updatePath.isPending}}
|
||||||
|
<li class="action">
|
||||||
|
<button disabled=true type="button" class="link button is-loading is-transparent">
|
||||||
|
loading
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
{{else}}
|
||||||
|
{{#if item.canEdit}}
|
||||||
|
<li class="action">
|
||||||
|
<a href={{href-to "vault.cluster.access.identity.aliases.edit" (pluralize item.parentType) item.id}}>
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{{/if}}
|
||||||
|
{{#if item.canDelete}}
|
||||||
|
<li class="action">
|
||||||
|
{{#confirm-action
|
||||||
|
data-test-item-delete=true
|
||||||
|
confirmButtonClasses="button is-primary"
|
||||||
|
buttonClasses="link"
|
||||||
|
onConfirmAction=(action "performTransaction" item)
|
||||||
|
confirmMessage=(concat "Are you sure you want to delete " item.id "?")
|
||||||
|
showConfirm=(get this (concat "shouldDelete-" item.id))
|
||||||
|
class=(if (get this (concat "shouldDelete-" item.id)) "message is-block is-warning is-outline")
|
||||||
|
containerClasses="message-body is-block"
|
||||||
|
messageClasses="is-block"
|
||||||
|
}}
|
||||||
|
Delete
|
||||||
|
{{/confirm-action}}
|
||||||
|
</li>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{{/with}}
|
||||||
|
{{/popup-menu}}
|
|
@ -0,0 +1,21 @@
|
||||||
|
{{#popup-menu name="member-edit-menu"}}
|
||||||
|
<nav class="menu">
|
||||||
|
<ul class="menu-list">
|
||||||
|
<li class="action">
|
||||||
|
{{#confirm-action
|
||||||
|
confirmButtonClasses="button is-primary"
|
||||||
|
confirmButtonText="Remove"
|
||||||
|
buttonClasses="link"
|
||||||
|
onConfirmAction=(action "performTransaction" model groupArray memberId)
|
||||||
|
confirmMessage=(concat "Are you sure you want to remove " memberId "?")
|
||||||
|
showConfirm=(get this (concat "shouldDelete-" memberId))
|
||||||
|
class=(if (get this (concat "shouldDelete-" memberId)) "message is-block is-warning is-outline")
|
||||||
|
containerClasses="message-body is-block"
|
||||||
|
messageClasses="is-block"
|
||||||
|
}}
|
||||||
|
Remove
|
||||||
|
{{/confirm-action}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{{/popup-menu}}
|
|
@ -0,0 +1,21 @@
|
||||||
|
{{#popup-menu name="metadata-edit-menu"}}
|
||||||
|
<nav class="menu">
|
||||||
|
<ul class="menu-list">
|
||||||
|
<li class="action">
|
||||||
|
{{#confirm-action
|
||||||
|
confirmButtonClasses="button is-primary"
|
||||||
|
confirmButtonText="Remove"
|
||||||
|
buttonClasses="link"
|
||||||
|
onConfirmAction=(action "performTransaction" model key)
|
||||||
|
confirmMessage=(concat "Are you sure you want to remove " key "?")
|
||||||
|
showConfirm=(get this (concat "shouldDelete-" key))
|
||||||
|
class=(if (get this (concat "shouldDelete-" key)) "message is-block is-warning is-outline")
|
||||||
|
containerClasses="message-body is-block"
|
||||||
|
messageClasses="is-block"
|
||||||
|
}}
|
||||||
|
Remove
|
||||||
|
{{/confirm-action}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{{/popup-menu}}
|
|
@ -0,0 +1,31 @@
|
||||||
|
{{#popup-menu name="policy-menu"}}
|
||||||
|
<nav class="menu">
|
||||||
|
<ul class="menu-list">
|
||||||
|
<li class="action">
|
||||||
|
<a href={{href-to "vault.cluster.policy.show" "acl" policyName }}>
|
||||||
|
View Policy
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="action">
|
||||||
|
<a href={{href-to "vault.cluster.policy.edit" "acl" policyName }}>
|
||||||
|
Edit Policy
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="action">
|
||||||
|
{{#confirm-action
|
||||||
|
confirmButtonClasses="button is-primary"
|
||||||
|
confirmButtonText="Remove"
|
||||||
|
buttonClasses="link"
|
||||||
|
onConfirmAction=(action "performTransaction" model policyName)
|
||||||
|
confirmMessage=(concat "Are you sure you want to remove " policyName "?")
|
||||||
|
showConfirm=(get this (concat "shouldDelete-" policyName))
|
||||||
|
class=(if (get this (concat "shouldDelete-" policyName)) "message is-block is-warning is-outline")
|
||||||
|
containerClasses="message-body is-block"
|
||||||
|
messageClasses="is-block"
|
||||||
|
}}
|
||||||
|
Remove from {{model.identityType}}
|
||||||
|
{{/confirm-action}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{{/popup-menu}}
|
|
@ -1,4 +1,5 @@
|
||||||
<ul>
|
<ul>
|
||||||
|
{{yield}}
|
||||||
{{#each secretPath as |path index|}}
|
{{#each secretPath as |path index|}}
|
||||||
<li class="{{if (is-active-route path.path path.model isExact=true) 'is-active'}}">
|
<li class="{{if (is-active-route path.path path.model isExact=true) 'is-active'}}">
|
||||||
<span class="sep">/</span>
|
<span class="sep">/</span>
|
||||||
|
|
|
@ -8,11 +8,15 @@
|
||||||
excludeIconClass=true
|
excludeIconClass=true
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
|
{{#if yieldWithoutColumn}}
|
||||||
|
{{yield}}
|
||||||
|
{{else}}
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p>
|
<p>
|
||||||
<strong>{{alertType.text}}</strong>
|
<strong>{{alertType.text}}</strong>
|
||||||
{{yield}}
|
{{yield}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
{{yield}}
|
|
@ -0,0 +1 @@
|
||||||
|
{{yield}}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue