Merge branch 'master' into new-guides
This commit is contained in:
commit
4d33d5fa34
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,14 +1,25 @@
|
|||
## 0.9.4 (Unreleased)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
* auth/centrify: Add CLI helper
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* api/renewer: Honor increment value in renew auth calls [GH-3904]
|
||||
* auth/approle: Fix inability to use limited-use-count secret IDs on
|
||||
replication performance secondaries
|
||||
* auth/approle: Cleanup of secret ID accessors during tidy and removal of
|
||||
dangling accessor entries [GH-3924]
|
||||
* auth/okta: Return configured durations as seconds, not nanoseconds [GH-3871]
|
||||
* auth/token: Token creation via the CLI no longer forces periodic token
|
||||
creation. Passing an explicit zero value for the period no longer create
|
||||
periodic tokens [GH-3880]
|
||||
periodic tokens. [GH-3880]
|
||||
* command/ssh: Create and reuse the api client [GH-3909]
|
||||
* storage/etcd3: Fix memory ballooning with standby instances [GH-3798]
|
||||
* storage/etcd3: Fix large lists (like token loading at startup) not being
|
||||
handled [GH-3772]
|
||||
* storage/zookeeper: Update vendoring to fix freezing issues [GH-3896]
|
||||
* plugin/gRPC: Fixed an issue with list requests and raw responses coming from
|
||||
plugins using gRPC transport [GH-3881]
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ func (r *Renewer) renewAuth() error {
|
|||
}
|
||||
|
||||
// Renew the auth.
|
||||
renewal, err := client.Auth().Token().RenewTokenAsSelf(token, 0)
|
||||
renewal, err := client.Auth().Token().RenewTokenAsSelf(token, r.increment)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/vault/helper/consts"
|
||||
"github.com/hashicorp/vault/helper/locksutil"
|
||||
"github.com/hashicorp/vault/helper/salt"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
|
@ -142,7 +143,9 @@ func (b *backend) invalidate(_ context.Context, key string) {
|
|||
// to delay the removal of SecretIDs by a minute.
|
||||
func (b *backend) periodicFunc(ctx context.Context, req *logical.Request) error {
|
||||
// Initiate clean-up of expired SecretID entries
|
||||
b.tidySecretID(ctx, req.Storage)
|
||||
if b.System().LocalMount() || !b.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary) {
|
||||
b.tidySecretID(ctx, req.Storage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
)
|
||||
|
@ -51,9 +52,14 @@ func (b *backend) pathLoginUpdateAliasLookahead(ctx context.Context, req *logica
|
|||
// Returns the Auth object indicating the authentication and authorization information
|
||||
// if the credentials provided are validated by the backend.
|
||||
func (b *backend) pathLoginUpdate(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
role, roleName, metadata, _, err := b.validateCredentials(ctx, req, data)
|
||||
if err != nil || role == nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf("failed to validate credentials: %v", err)), nil
|
||||
role, roleName, metadata, _, userErr, intErr := b.validateCredentials(ctx, req, data)
|
||||
switch {
|
||||
case intErr != nil:
|
||||
return nil, errwrap.Wrapf("failed to validate credentials: {{err}}", intErr)
|
||||
case userErr != nil:
|
||||
return logical.ErrorResponse(fmt.Sprintf("failed to validate credentials: %v", userErr)), nil
|
||||
case role == nil:
|
||||
return logical.ErrorResponse("failed to validate credentials; could not find role"), nil
|
||||
}
|
||||
|
||||
// Always include the role name, for later filtering
|
||||
|
|
|
@ -38,6 +38,16 @@ func (b *backend) tidySecretID(ctx context.Context, s logical.Storage) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// List all the accessors and add them all to a map
|
||||
accessorHashes, err := s.List(ctx, "accessor/")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
accessorMap := make(map[string]bool, len(accessorHashes))
|
||||
for _, accessorHash := range accessorHashes {
|
||||
accessorMap[accessorHash] = true
|
||||
}
|
||||
|
||||
var result error
|
||||
for _, roleNameHMAC := range roleNameHMACs {
|
||||
// roleNameHMAC will already have a '/' suffix. Don't append another one.
|
||||
|
@ -77,14 +87,46 @@ func (b *backend) tidySecretID(ctx context.Context, s logical.Storage) error {
|
|||
|
||||
// ExpirationTime not being set indicates non-expiring SecretIDs
|
||||
if !result.ExpirationTime.IsZero() && time.Now().After(result.ExpirationTime) {
|
||||
// Clean up the accessor of the secret ID first
|
||||
err = b.deleteSecretIDAccessorEntry(ctx, s, result.SecretIDAccessor)
|
||||
if err != nil {
|
||||
lock.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.Delete(ctx, entryIndex); err != nil {
|
||||
lock.Unlock()
|
||||
return fmt.Errorf("error deleting SecretID %s from storage: %s", secretIDHMAC, err)
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, the secret ID is not expired and is valid. Delete
|
||||
// the corresponding accessor from the accessorMap. This will leave
|
||||
// only the dangling accessors in the map which can then be cleaned
|
||||
// up later.
|
||||
salt, err := b.Salt()
|
||||
if err != nil {
|
||||
lock.Unlock()
|
||||
return err
|
||||
}
|
||||
delete(accessorMap, salt.SaltID(result.SecretIDAccessor))
|
||||
|
||||
lock.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// Accessor indexes were not getting cleaned up until 0.9.3. This is a fix
|
||||
// to clean up the dangling accessor entries.
|
||||
for accessorHash, _ := range accessorMap {
|
||||
// Ideally, locking should be performed here. But for that, accessors
|
||||
// are required in plaintext, which are not available. Hence performing
|
||||
// a racy cleanup.
|
||||
err = s.Delete(ctx, "accessor/"+accessorHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
package approle
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
)
|
||||
|
||||
func TestAppRole_TidyDanglingAccessors(t *testing.T) {
|
||||
var resp *logical.Response
|
||||
var err error
|
||||
b, storage := createBackendWithStorage(t)
|
||||
|
||||
// Create a role
|
||||
createRole(t, b, storage, "role1", "a,b,c")
|
||||
|
||||
// Create a secret-id
|
||||
roleSecretIDReq := &logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: "role/role1/secret-id",
|
||||
Storage: storage,
|
||||
}
|
||||
resp, err = b.HandleRequest(context.Background(), roleSecretIDReq)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
accessorHashes, err := storage.List(context.Background(), "accessor/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(accessorHashes) != 1 {
|
||||
t.Fatalf("bad: len(accessorHashes); expect 1, got %d", len(accessorHashes))
|
||||
}
|
||||
|
||||
entry1, err := logical.StorageEntryJSON(
|
||||
"accessor/invalid1",
|
||||
&secretIDAccessorStorageEntry{
|
||||
SecretIDHMAC: "samplesecretidhmac",
|
||||
},
|
||||
)
|
||||
err = storage.Put(context.Background(), entry1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
entry2, err := logical.StorageEntryJSON(
|
||||
"accessor/invalid2",
|
||||
&secretIDAccessorStorageEntry{
|
||||
SecretIDHMAC: "samplesecretidhmac2",
|
||||
},
|
||||
)
|
||||
err = storage.Put(context.Background(), entry2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
accessorHashes, err = storage.List(context.Background(), "accessor/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(accessorHashes) != 3 {
|
||||
t.Fatalf("bad: len(accessorHashes); expect 3, got %d", len(accessorHashes))
|
||||
}
|
||||
|
||||
err = b.tidySecretID(context.Background(), storage)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
accessorHashes, err = storage.List(context.Background(), "accessor/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(accessorHashes) != 1 {
|
||||
t.Fatalf("bad: len(accessorHashes); expect 1, got %d", len(accessorHashes))
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/hashicorp/vault/helper/cidrutil"
|
||||
"github.com/hashicorp/vault/helper/locksutil"
|
||||
|
@ -95,26 +96,26 @@ func (b *backend) validateRoleID(ctx context.Context, s logical.Storage, roleID
|
|||
}
|
||||
|
||||
// Validates the supplied RoleID and SecretID
|
||||
func (b *backend) validateCredentials(ctx context.Context, req *logical.Request, data *framework.FieldData) (*roleStorageEntry, string, map[string]string, string, error) {
|
||||
func (b *backend) validateCredentials(ctx context.Context, req *logical.Request, data *framework.FieldData) (*roleStorageEntry, string, map[string]string, string, error, error) {
|
||||
metadata := make(map[string]string)
|
||||
// RoleID must be supplied during every login
|
||||
roleID := strings.TrimSpace(data.Get("role_id").(string))
|
||||
if roleID == "" {
|
||||
return nil, "", metadata, "", fmt.Errorf("missing role_id")
|
||||
return nil, "", metadata, "", fmt.Errorf("missing role_id"), nil
|
||||
}
|
||||
|
||||
// Validate the RoleID and get the Role entry
|
||||
role, roleName, err := b.validateRoleID(ctx, req.Storage, roleID)
|
||||
if err != nil {
|
||||
return nil, "", metadata, "", err
|
||||
return nil, "", metadata, "", nil, err
|
||||
}
|
||||
if role == nil || roleName == "" {
|
||||
return nil, "", metadata, "", fmt.Errorf("failed to validate role_id")
|
||||
return nil, "", metadata, "", fmt.Errorf("failed to validate role_id"), nil
|
||||
}
|
||||
|
||||
// Calculate the TTL boundaries since this reflects the properties of the token issued
|
||||
if role.TokenTTL, role.TokenMaxTTL, err = b.SanitizeTTL(role.TokenTTL, role.TokenMaxTTL); err != nil {
|
||||
return nil, "", metadata, "", err
|
||||
return nil, "", metadata, "", nil, err
|
||||
}
|
||||
|
||||
var secretID string
|
||||
|
@ -123,7 +124,7 @@ func (b *backend) validateCredentials(ctx context.Context, req *logical.Request,
|
|||
// to be specified and validate it.
|
||||
secretID = strings.TrimSpace(data.Get("secret_id").(string))
|
||||
if secretID == "" {
|
||||
return nil, "", metadata, "", fmt.Errorf("missing secret_id")
|
||||
return nil, "", metadata, "", fmt.Errorf("missing secret_id"), nil
|
||||
}
|
||||
|
||||
if role.LowerCaseRoleName {
|
||||
|
@ -135,29 +136,29 @@ func (b *backend) validateCredentials(ctx context.Context, req *logical.Request,
|
|||
var valid bool
|
||||
valid, metadata, err = b.validateBindSecretID(ctx, req, roleName, secretID, role.HMACKey, role.BoundCIDRList)
|
||||
if err != nil {
|
||||
return nil, "", metadata, "", err
|
||||
return nil, "", metadata, "", nil, err
|
||||
}
|
||||
if !valid {
|
||||
return nil, "", metadata, "", fmt.Errorf("invalid secret_id %q", secretID)
|
||||
return nil, "", metadata, "", fmt.Errorf("invalid secret_id %q", secretID), nil
|
||||
}
|
||||
}
|
||||
|
||||
if role.BoundCIDRList != "" {
|
||||
// If 'bound_cidr_list' was set, verify the CIDR restrictions
|
||||
if req.Connection == nil || req.Connection.RemoteAddr == "" {
|
||||
return nil, "", metadata, "", fmt.Errorf("failed to get connection information")
|
||||
return nil, "", metadata, "", fmt.Errorf("failed to get connection information"), nil
|
||||
}
|
||||
|
||||
belongs, err := cidrutil.IPBelongsToCIDRBlocksString(req.Connection.RemoteAddr, role.BoundCIDRList, ",")
|
||||
if err != nil {
|
||||
return nil, "", metadata, "", fmt.Errorf("failed to verify the CIDR restrictions set on the role: %v", err)
|
||||
return nil, "", metadata, "", nil, errwrap.Wrapf("failed to verify the CIDR restrictions set on the role: {{err}}", err)
|
||||
}
|
||||
if !belongs {
|
||||
return nil, "", metadata, "", fmt.Errorf("source address %q unauthorized through CIDR restrictions on the role", req.Connection.RemoteAddr)
|
||||
return nil, "", metadata, "", fmt.Errorf("source address %q unauthorized through CIDR restrictions on the role", req.Connection.RemoteAddr), nil
|
||||
}
|
||||
}
|
||||
|
||||
return role, roleName, metadata, secretID, nil
|
||||
return role, roleName, metadata, secretID, nil, nil
|
||||
}
|
||||
|
||||
// validateBindSecretID is used to determine if the given SecretID is a valid one.
|
||||
|
@ -250,9 +251,9 @@ func (b *backend) validateBindSecretID(ctx context.Context, req *logical.Request
|
|||
result.SecretIDNumUses -= 1
|
||||
result.LastUpdatedTime = time.Now()
|
||||
if entry, err := logical.StorageEntryJSON(entryIndex, &result); err != nil {
|
||||
return false, nil, fmt.Errorf("failed to decrement the use count for secret ID %q", secretID)
|
||||
return false, nil, fmt.Errorf("failed to create storage entry while decrementing the secret ID use count: %v", err)
|
||||
} else if err = req.Storage.Put(ctx, entry); err != nil {
|
||||
return false, nil, fmt.Errorf("failed to decrement the use count for secret ID %q", secretID)
|
||||
return false, nil, fmt.Errorf("failed to decrement the secret ID use count: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/aws/aws-sdk-go/aws/endpoints"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
"github.com/hashicorp/vault/helper/consts"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
"github.com/patrickmn/go-cache"
|
||||
|
@ -143,29 +144,33 @@ func (b *backend) periodicFunc(ctx context.Context, req *logical.Request) error
|
|||
// Run the tidy operations for the first time. Then run it when current
|
||||
// time matches the nextTidyTime.
|
||||
if b.nextTidyTime.IsZero() || !time.Now().Before(b.nextTidyTime) {
|
||||
// safety_buffer defaults to 180 days for roletag blacklist
|
||||
safety_buffer := 15552000
|
||||
tidyBlacklistConfigEntry, err := b.lockedConfigTidyRoleTags(ctx, req.Storage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
skipBlacklistTidy := false
|
||||
// check if tidying of role tags was configured
|
||||
if tidyBlacklistConfigEntry != nil {
|
||||
// check if periodic tidying of role tags was disabled
|
||||
if tidyBlacklistConfigEntry.DisablePeriodicTidy {
|
||||
skipBlacklistTidy = true
|
||||
if b.System().LocalMount() || !b.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary) {
|
||||
// safety_buffer defaults to 180 days for roletag blacklist
|
||||
safety_buffer := 15552000
|
||||
tidyBlacklistConfigEntry, err := b.lockedConfigTidyRoleTags(ctx, req.Storage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
skipBlacklistTidy := false
|
||||
// check if tidying of role tags was configured
|
||||
if tidyBlacklistConfigEntry != nil {
|
||||
// check if periodic tidying of role tags was disabled
|
||||
if tidyBlacklistConfigEntry.DisablePeriodicTidy {
|
||||
skipBlacklistTidy = true
|
||||
}
|
||||
// overwrite the default safety_buffer with the configured value
|
||||
safety_buffer = tidyBlacklistConfigEntry.SafetyBuffer
|
||||
}
|
||||
// tidy role tags if explicitly not disabled
|
||||
if !skipBlacklistTidy {
|
||||
b.tidyBlacklistRoleTag(ctx, req.Storage, safety_buffer)
|
||||
}
|
||||
// overwrite the default safety_buffer with the configured value
|
||||
safety_buffer = tidyBlacklistConfigEntry.SafetyBuffer
|
||||
}
|
||||
// tidy role tags if explicitly not disabled
|
||||
if !skipBlacklistTidy {
|
||||
b.tidyBlacklistRoleTag(ctx, req.Storage, safety_buffer)
|
||||
}
|
||||
|
||||
// reset the safety_buffer to 72h
|
||||
safety_buffer = 259200
|
||||
// We don't check for replication state for whitelist identities as
|
||||
// these are locally stored
|
||||
|
||||
safety_buffer := 259200
|
||||
tidyWhitelistConfigEntry, err := b.lockedConfigTidyIdentities(ctx, req.Storage)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -287,7 +287,7 @@ func TestBackend_ConfigTidyIdentities(t *testing.T) {
|
|||
t.Fatalf("failed to read config/tidy/identity-whitelist endpoint")
|
||||
}
|
||||
if resp.Data["safety_buffer"].(int) != 60 || !resp.Data["disable_periodic_tidy"].(bool) {
|
||||
t.Fatalf("bad: expected: safety_buffer:60 disable_periodic_tidy:true actual: safety_buffer:%s disable_periodic_tidy:%t\n", resp.Data["safety_buffer"].(int), resp.Data["disable_periodic_tidy"].(bool))
|
||||
t.Fatalf("bad: expected: safety_buffer:60 disable_periodic_tidy:true actual: safety_buffer:%d disable_periodic_tidy:%t\n", resp.Data["safety_buffer"].(int), resp.Data["disable_periodic_tidy"].(bool))
|
||||
}
|
||||
|
||||
// test delete operation
|
||||
|
@ -342,7 +342,7 @@ func TestBackend_ConfigTidyRoleTags(t *testing.T) {
|
|||
t.Fatalf("failed to read config/tidy/roletag-blacklist endpoint")
|
||||
}
|
||||
if resp.Data["safety_buffer"].(int) != 60 || !resp.Data["disable_periodic_tidy"].(bool) {
|
||||
t.Fatalf("bad: expected: safety_buffer:60 disable_periodic_tidy:true actual: safety_buffer:%s disable_periodic_tidy:%t\n", resp.Data["safety_buffer"].(int), resp.Data["disable_periodic_tidy"].(bool))
|
||||
t.Fatalf("bad: expected: safety_buffer:60 disable_periodic_tidy:true actual: safety_buffer:%d disable_periodic_tidy:%t\n", resp.Data["safety_buffer"].(int), resp.Data["disable_periodic_tidy"].(bool))
|
||||
}
|
||||
|
||||
// test delete operation
|
||||
|
@ -1587,7 +1587,7 @@ func TestBackendAcc_LoginWithCallerIdentity(t *testing.T) {
|
|||
// and ensure a renew no longer works
|
||||
resp, err = b.pathLoginRenew(context.Background(), renewReq, empty_login_fd)
|
||||
if err == nil || (resp != nil && !resp.IsError()) {
|
||||
t.Errorf("bad: expected failed renew due to changed AWS role ID: resp: %#v", resp, err)
|
||||
t.Errorf("bad: expected failed renew due to changed AWS role ID: resp: %#v", resp)
|
||||
}
|
||||
// Undo the fake resolver...
|
||||
b.resolveArnToUniqueIDFunc = b.resolveArnToRealUniqueId
|
||||
|
|
|
@ -319,23 +319,23 @@ func (b *backend) parseAndVerifyRoleTagValue(ctx context.Context, s logical.Stor
|
|||
for _, tagItem := range tagItems {
|
||||
var err error
|
||||
switch {
|
||||
case strings.Contains(tagItem, "i="):
|
||||
case strings.HasPrefix(tagItem, "i="):
|
||||
rTag.InstanceID = strings.TrimPrefix(tagItem, "i=")
|
||||
case strings.Contains(tagItem, "r="):
|
||||
case strings.HasPrefix(tagItem, "r="):
|
||||
rTag.Role = strings.TrimPrefix(tagItem, "r=")
|
||||
case strings.Contains(tagItem, "p="):
|
||||
case strings.HasPrefix(tagItem, "p="):
|
||||
rTag.Policies = strings.Split(strings.TrimPrefix(tagItem, "p="), ",")
|
||||
case strings.Contains(tagItem, "d="):
|
||||
case strings.HasPrefix(tagItem, "d="):
|
||||
rTag.DisallowReauthentication, err = strconv.ParseBool(strings.TrimPrefix(tagItem, "d="))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case strings.Contains(tagItem, "m="):
|
||||
case strings.HasPrefix(tagItem, "m="):
|
||||
rTag.AllowInstanceMigration, err = strconv.ParseBool(strings.TrimPrefix(tagItem, "m="))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case strings.Contains(tagItem, "t="):
|
||||
case strings.HasPrefix(tagItem, "t="):
|
||||
rTag.MaxTTL, err = time.ParseDuration(fmt.Sprintf("%ss", strings.TrimPrefix(tagItem, "t=")))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -1062,8 +1062,7 @@ func testConnState(certPath, keyPath, rootCertPath string) (tls.ConnectionState,
|
|||
InsecureSkipVerify: false,
|
||||
RootCAs: rootCAs,
|
||||
}
|
||||
dialConf := new(tls.Config)
|
||||
*dialConf = *listenConf
|
||||
dialConf := listenConf.Clone()
|
||||
// start a server
|
||||
list, err := tls.Listen("tcp", "127.0.0.1:0", listenConf)
|
||||
if err != nil {
|
||||
|
|
|
@ -61,7 +61,7 @@ certificate.`,
|
|||
|
||||
"policies": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: "Comma-seperated list of policies.",
|
||||
Description: "Comma-separated list of policies.",
|
||||
},
|
||||
|
||||
"lease": &framework.FieldSchema{
|
||||
|
@ -78,7 +78,7 @@ Defaults to system/backend default TTL time.`,
|
|||
"max_ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
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.`,
|
||||
},
|
||||
"period": &framework.FieldSchema{
|
||||
|
|
|
@ -261,7 +261,7 @@ func TestBackend_configDefaultsAfterUpdate(t *testing.T) {
|
|||
|
||||
defaultDenyNullBind := true
|
||||
if cfg["deny_null_bind"] != defaultDenyNullBind {
|
||||
t.Errorf("Default mismatch: deny_null_bind. Expected: '%s', received :'%s'", defaultDenyNullBind, cfg["deny_null_bind"])
|
||||
t.Errorf("Default mismatch: deny_null_bind. Expected: '%t', received :'%s'", defaultDenyNullBind, cfg["deny_null_bind"])
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -44,7 +44,7 @@ func Backend() *backend {
|
|||
secretAccessKeys(&b),
|
||||
},
|
||||
|
||||
WALRollback: walRollback,
|
||||
WALRollback: b.walRollback,
|
||||
WALRollbackMinAge: 5 * time.Minute,
|
||||
BackendType: logical.TypeLogical,
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/vault/helper/consts"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
)
|
||||
|
@ -12,7 +13,11 @@ var walRollbackMap = map[string]framework.WALRollbackFunc{
|
|||
"user": pathUserRollback,
|
||||
}
|
||||
|
||||
func walRollback(ctx context.Context, req *logical.Request, kind string, data interface{}) error {
|
||||
func (b *backend) walRollback(ctx context.Context, req *logical.Request, kind string, data interface{}) error {
|
||||
if !b.System().LocalMount() && b.System().ReplicationState().HasState(consts.ReplicationPerformancePrimary) {
|
||||
return nil
|
||||
}
|
||||
|
||||
f, ok := walRollbackMap[kind]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown type to rollback")
|
||||
|
|
|
@ -143,7 +143,7 @@ func TestBackend_RoleUpgrade(t *testing.T) {
|
|||
}
|
||||
|
||||
if !reflect.DeepEqual(role, roleEnt) {
|
||||
t.Fatal("bad role %#v", role)
|
||||
t.Fatalf("bad role %#v", role)
|
||||
}
|
||||
|
||||
// Upgrade case
|
||||
|
@ -162,7 +162,7 @@ func TestBackend_RoleUpgrade(t *testing.T) {
|
|||
}
|
||||
|
||||
if !reflect.DeepEqual(role, roleEnt) {
|
||||
t.Fatal("bad role %#v", role)
|
||||
t.Fatalf("bad role %#v", role)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ This path lets you manage the roles that can be created with this backend.
|
|||
|
||||
The "sql" parameter customizes the SQL string used to create the login to
|
||||
the server. The parameter can be a sequence of SQL queries, each semi-colon
|
||||
seperated. Some substitution will be done to the SQL string for certain keys.
|
||||
separated. Some substitution will be done to the SQL string for certain keys.
|
||||
The names of the variables must be surrounded by "{{" and "}}" to be replaced.
|
||||
|
||||
* "name" - The random username generated for the DB user.
|
||||
|
|
|
@ -192,7 +192,7 @@ const pathRoleHelpDesc = `
|
|||
This path lets you manage the roles that can be created with this backend.
|
||||
|
||||
The "sql" parameter customizes the SQL string used to create the role.
|
||||
This can be a sequence of SQL queries, each semi-colon seperated. Some
|
||||
This can be a sequence of SQL queries, each semi-colon separated. Some
|
||||
substitution will be done to the SQL string for certain keys.
|
||||
The names of the variables must be surrounded by "{{" and "}}" to be replaced.
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/helper/consts"
|
||||
"github.com/hashicorp/vault/helper/parseutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
|
@ -315,7 +316,7 @@ func (b *backend) getRole(ctx context.Context, s logical.Storage, n string) (*ro
|
|||
modified = true
|
||||
}
|
||||
|
||||
if modified {
|
||||
if modified && (b.System().LocalMount() || !b.System().ReplicationState().HasState(consts.ReplicationPerformanceSecondary)) {
|
||||
jsonEntry, err := logical.StorageEntryJSON("role/"+n, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -45,7 +45,6 @@ type BaseCommand struct {
|
|||
|
||||
tokenHelper token.TokenHelper
|
||||
|
||||
// For testing
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
|
@ -110,6 +109,8 @@ func (c *BaseCommand) Client() (*api.Client, error) {
|
|||
client.SetToken(token)
|
||||
}
|
||||
|
||||
c.client = client
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -185,11 +185,12 @@ func init() {
|
|||
}
|
||||
|
||||
loginHandlers := map[string]LoginHandler{
|
||||
"aws": &credAws.CLIHandler{},
|
||||
"cert": &credCert.CLIHandler{},
|
||||
"github": &credGitHub.CLIHandler{},
|
||||
"ldap": &credLdap.CLIHandler{},
|
||||
"okta": &credOkta.CLIHandler{},
|
||||
"aws": &credAws.CLIHandler{},
|
||||
"centrify": &credCentrify.CLIHandler{},
|
||||
"cert": &credCert.CLIHandler{},
|
||||
"github": &credGitHub.CLIHandler{},
|
||||
"ldap": &credLdap.CLIHandler{},
|
||||
"okta": &credOkta.CLIHandler{},
|
||||
"radius": &credUserpass.CLIHandler{
|
||||
DefaultMount: "radius",
|
||||
},
|
||||
|
|
|
@ -192,7 +192,7 @@ func TestIdentityStore_Integ_GroupAliases(t *testing.T) {
|
|||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("expected entity ID %q to be part of Italians group")
|
||||
t.Fatalf("expected entity ID %q to be part of Italians group", entityID)
|
||||
}
|
||||
|
||||
secret, err = client.Logical().Read("identity/group/id/" + scientistsGroupID)
|
||||
|
@ -207,7 +207,7 @@ func TestIdentityStore_Integ_GroupAliases(t *testing.T) {
|
|||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("expected entity ID %q to be part of Scientists group")
|
||||
t.Fatalf("expected entity ID %q to be part of Scientists group", entityID)
|
||||
}
|
||||
|
||||
secret, err = client.Logical().Read("identity/group/id/" + devopsGroupID)
|
||||
|
@ -222,7 +222,7 @@ func TestIdentityStore_Integ_GroupAliases(t *testing.T) {
|
|||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("expected entity ID %q to be part of devops group")
|
||||
t.Fatalf("expected entity ID %q to be part of devops group", entityID)
|
||||
}
|
||||
|
||||
identityStore := cores[0].IdentityStore()
|
||||
|
@ -308,7 +308,7 @@ func TestIdentityStore_Integ_GroupAliases(t *testing.T) {
|
|||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("expected entity ID %q to be part of Italians group")
|
||||
t.Fatalf("expected entity ID %q to be part of Italians group", entityID)
|
||||
}
|
||||
|
||||
secret, err = client.Logical().Read("identity/group/id/" + scientistsGroupID)
|
||||
|
@ -323,7 +323,7 @@ func TestIdentityStore_Integ_GroupAliases(t *testing.T) {
|
|||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("expected entity ID %q to be part of Italians group")
|
||||
t.Fatalf("expected entity ID %q to be part of scientists group", entityID)
|
||||
}
|
||||
|
||||
secret, err = client.Logical().Read("identity/group/id/" + devopsGroupID)
|
||||
|
@ -339,7 +339,7 @@ func TestIdentityStore_Integ_GroupAliases(t *testing.T) {
|
|||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("expected entity ID %q to be part of devops group")
|
||||
t.Fatalf("expected entity ID %q to be part of devops group", entityID)
|
||||
}
|
||||
|
||||
// Remove user tesla from the devops group in LDAP backend
|
||||
|
|
|
@ -36,7 +36,7 @@ func TestTCPListener_tls(t *testing.T) {
|
|||
wd, _ := os.Getwd()
|
||||
wd += "/test-fixtures/reload/"
|
||||
|
||||
td, err := ioutil.TempDir("", fmt.Sprintf("vault-test-%d", rand.New(rand.NewSource(time.Now().Unix())).Int63))
|
||||
td, err := ioutil.TempDir("", fmt.Sprintf("vault-test-%d", rand.New(rand.NewSource(time.Now().Unix())).Int63()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -244,6 +244,13 @@ func (c *SSHCommand) Run(args []string) int {
|
|||
sshArgs = args[1:]
|
||||
}
|
||||
|
||||
// Set the client in the command
|
||||
_, err = c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
// Credentials are generated only against a registered role. If user
|
||||
// does not specify a role with the SSH command, then lookup API is used
|
||||
// to fetch all the roles with which this IP is associated. If there is
|
||||
|
@ -331,13 +338,7 @@ func (c *SSHCommand) handleTypeCA(username, ip string, sshArgs []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
sshClient := client.SSHWithMountPoint(c.flagMountPoint)
|
||||
sshClient := c.client.SSHWithMountPoint(c.flagMountPoint)
|
||||
|
||||
// Attempt to sign the public key
|
||||
secret, err := sshClient.SignKey(c.flagRole, map[string]interface{}{
|
||||
|
@ -611,12 +612,7 @@ func (c *SSHCommand) handleTypeDynamic(username, ip string, sshArgs []string) in
|
|||
// generateCredential generates a credential for the given role and returns the
|
||||
// decoded secret data.
|
||||
func (c *SSHCommand) generateCredential(username, ip string) (*api.Secret, *SSHCredentialResp, error) {
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sshClient := client.SSHWithMountPoint(c.flagMountPoint)
|
||||
sshClient := c.client.SSHWithMountPoint(c.flagMountPoint)
|
||||
|
||||
// Attempt to generate the credential.
|
||||
secret, err := sshClient.Credential(c.flagRole, map[string]interface{}{
|
||||
|
@ -683,11 +679,7 @@ func (c *SSHCommand) defaultRole(mountPoint, ip string) (string, error) {
|
|||
data := map[string]interface{}{
|
||||
"ip": ip,
|
||||
}
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
secret, err := client.Logical().Write(mountPoint+"/lookup", data)
|
||||
secret, err := c.client.Logical().Write(mountPoint+"/lookup", data)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error finding roles for IP %q: %q", ip, err)
|
||||
|
||||
|
|
|
@ -52,12 +52,12 @@ func ParseHexFormatted(in, sep string) []byte {
|
|||
// of the marshaled public key
|
||||
func GetSubjKeyID(privateKey crypto.Signer) ([]byte, error) {
|
||||
if privateKey == nil {
|
||||
return nil, errutil.InternalError{"passed-in private key is nil"}
|
||||
return nil, errutil.InternalError{Err: "passed-in private key is nil"}
|
||||
}
|
||||
|
||||
marshaledKey, err := x509.MarshalPKIXPublicKey(privateKey.Public())
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{fmt.Sprintf("error marshalling public key: %s", err)}
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("error marshalling public key: %s", err)}
|
||||
}
|
||||
|
||||
subjKeyID := sha1.Sum(marshaledKey)
|
||||
|
@ -71,7 +71,7 @@ func ParsePKIMap(data map[string]interface{}) (*ParsedCertBundle, error) {
|
|||
result := &CertBundle{}
|
||||
err := mapstructure.Decode(data, result)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{err.Error()}
|
||||
return nil, errutil.UserError{Err: err.Error()}
|
||||
}
|
||||
|
||||
return result.ToParsedCertBundle()
|
||||
|
@ -97,7 +97,7 @@ func ParsePKIJSON(input []byte) (*ParsedCertBundle, error) {
|
|||
return ParsePKIMap(secret.Data)
|
||||
}
|
||||
|
||||
return nil, errutil.UserError{"unable to parse out of either secret data or a secret object"}
|
||||
return nil, errutil.UserError{Err: "unable to parse out of either secret data or a secret object"}
|
||||
}
|
||||
|
||||
// ParsePEMBundle takes a string of concatenated PEM-format certificate
|
||||
|
@ -106,7 +106,7 @@ func ParsePKIJSON(input []byte) (*ParsedCertBundle, error) {
|
|||
// certificates may follow. There must be at most one private key.
|
||||
func ParsePEMBundle(pemBundle string) (*ParsedCertBundle, error) {
|
||||
if len(pemBundle) == 0 {
|
||||
return nil, errutil.UserError{"empty pem bundle"}
|
||||
return nil, errutil.UserError{Err: "empty pem bundle"}
|
||||
}
|
||||
|
||||
pemBundle = strings.TrimSpace(pemBundle)
|
||||
|
@ -119,12 +119,12 @@ func ParsePEMBundle(pemBundle string) (*ParsedCertBundle, error) {
|
|||
for len(pemBytes) > 0 {
|
||||
pemBlock, pemBytes = pem.Decode(pemBytes)
|
||||
if pemBlock == nil {
|
||||
return nil, errutil.UserError{"no data found"}
|
||||
return nil, errutil.UserError{Err: "no data found"}
|
||||
}
|
||||
|
||||
if signer, err := x509.ParseECPrivateKey(pemBlock.Bytes); err == nil {
|
||||
if parsedBundle.PrivateKeyType != UnknownPrivateKey {
|
||||
return nil, errutil.UserError{"more than one private key given; provide only one private key in the bundle"}
|
||||
return nil, errutil.UserError{Err: "more than one private key given; provide only one private key in the bundle"}
|
||||
}
|
||||
parsedBundle.PrivateKeyFormat = ECBlock
|
||||
parsedBundle.PrivateKeyType = ECPrivateKey
|
||||
|
@ -133,7 +133,7 @@ func ParsePEMBundle(pemBundle string) (*ParsedCertBundle, error) {
|
|||
|
||||
} else if signer, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes); err == nil {
|
||||
if parsedBundle.PrivateKeyType != UnknownPrivateKey {
|
||||
return nil, errutil.UserError{"more than one private key given; provide only one private key in the bundle"}
|
||||
return nil, errutil.UserError{Err: "more than one private key given; provide only one private key in the bundle"}
|
||||
}
|
||||
parsedBundle.PrivateKeyType = RSAPrivateKey
|
||||
parsedBundle.PrivateKeyFormat = PKCS1Block
|
||||
|
@ -143,7 +143,7 @@ func ParsePEMBundle(pemBundle string) (*ParsedCertBundle, error) {
|
|||
parsedBundle.PrivateKeyFormat = PKCS8Block
|
||||
|
||||
if parsedBundle.PrivateKeyType != UnknownPrivateKey {
|
||||
return nil, errutil.UserError{"More than one private key given; provide only one private key in the bundle"}
|
||||
return nil, errutil.UserError{Err: "More than one private key given; provide only one private key in the bundle"}
|
||||
}
|
||||
switch signer := signer.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
|
|
|
@ -147,7 +147,7 @@ func (c *CertBundle) ToParsedCertBundle() (*ParsedCertBundle, error) {
|
|||
if len(c.PrivateKey) > 0 {
|
||||
pemBlock, _ = pem.Decode([]byte(c.PrivateKey))
|
||||
if pemBlock == nil {
|
||||
return nil, errutil.UserError{"Error decoding private key from cert bundle"}
|
||||
return nil, errutil.UserError{Err: "Error decoding private key from cert bundle"}
|
||||
}
|
||||
|
||||
result.PrivateKeyBytes = pemBlock.Bytes
|
||||
|
@ -161,7 +161,7 @@ func (c *CertBundle) ToParsedCertBundle() (*ParsedCertBundle, error) {
|
|||
case PKCS8Block:
|
||||
t, err := getPKCS8Type(pemBlock.Bytes)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{fmt.Sprintf("Error getting key type from pkcs#8: %v", err)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Error getting key type from pkcs#8: %v", err)}
|
||||
}
|
||||
result.PrivateKeyType = t
|
||||
switch t {
|
||||
|
@ -171,24 +171,24 @@ func (c *CertBundle) ToParsedCertBundle() (*ParsedCertBundle, error) {
|
|||
c.PrivateKeyType = RSAPrivateKey
|
||||
}
|
||||
default:
|
||||
return nil, errutil.UserError{fmt.Sprintf("Unsupported key block type: %s", pemBlock.Type)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Unsupported key block type: %s", pemBlock.Type)}
|
||||
}
|
||||
|
||||
result.PrivateKey, err = result.getSigner()
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{fmt.Sprintf("Error getting signer: %s", err)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Error getting signer: %s", err)}
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.Certificate) > 0 {
|
||||
pemBlock, _ = pem.Decode([]byte(c.Certificate))
|
||||
if pemBlock == nil {
|
||||
return nil, errutil.UserError{"Error decoding certificate from cert bundle"}
|
||||
return nil, errutil.UserError{Err: "Error decoding certificate from cert bundle"}
|
||||
}
|
||||
result.CertificateBytes = pemBlock.Bytes
|
||||
result.Certificate, err = x509.ParseCertificate(result.CertificateBytes)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{"Error encountered parsing certificate bytes from raw bundle"}
|
||||
return nil, errutil.UserError{Err: "Error encountered parsing certificate bytes from raw bundle"}
|
||||
}
|
||||
}
|
||||
switch {
|
||||
|
@ -196,12 +196,12 @@ func (c *CertBundle) ToParsedCertBundle() (*ParsedCertBundle, error) {
|
|||
for _, cert := range c.CAChain {
|
||||
pemBlock, _ := pem.Decode([]byte(cert))
|
||||
if pemBlock == nil {
|
||||
return nil, errutil.UserError{"Error decoding certificate from cert bundle"}
|
||||
return nil, errutil.UserError{Err: "Error decoding certificate from cert bundle"}
|
||||
}
|
||||
|
||||
parsedCert, err := x509.ParseCertificate(pemBlock.Bytes)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{"Error encountered parsing certificate bytes from raw bundle"}
|
||||
return nil, errutil.UserError{Err: "Error encountered parsing certificate bytes from raw bundle"}
|
||||
}
|
||||
|
||||
certBlock := &CertBlock{
|
||||
|
@ -215,12 +215,12 @@ func (c *CertBundle) ToParsedCertBundle() (*ParsedCertBundle, error) {
|
|||
case len(c.IssuingCA) > 0:
|
||||
pemBlock, _ = pem.Decode([]byte(c.IssuingCA))
|
||||
if pemBlock == nil {
|
||||
return nil, errutil.UserError{"Error decoding ca certificate from cert bundle"}
|
||||
return nil, errutil.UserError{Err: "Error decoding ca certificate from cert bundle"}
|
||||
}
|
||||
|
||||
parsedCert, err := x509.ParseCertificate(pemBlock.Bytes)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{"Error encountered parsing certificate bytes from raw bundle3"}
|
||||
return nil, errutil.UserError{Err: "Error encountered parsing certificate bytes from raw bundle3"}
|
||||
}
|
||||
|
||||
result.SerialNumber = result.Certificate.SerialNumber
|
||||
|
@ -343,20 +343,20 @@ func (p *ParsedCertBundle) getSigner() (crypto.Signer, error) {
|
|||
var err error
|
||||
|
||||
if p.PrivateKeyBytes == nil || len(p.PrivateKeyBytes) == 0 {
|
||||
return nil, errutil.UserError{"Given parsed cert bundle does not have private key information"}
|
||||
return nil, errutil.UserError{Err: "Given parsed cert bundle does not have private key information"}
|
||||
}
|
||||
|
||||
switch p.PrivateKeyFormat {
|
||||
case ECBlock:
|
||||
signer, err = x509.ParseECPrivateKey(p.PrivateKeyBytes)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{fmt.Sprintf("Unable to parse CA's private EC key: %s", err)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Unable to parse CA's private EC key: %s", err)}
|
||||
}
|
||||
|
||||
case PKCS1Block:
|
||||
signer, err = x509.ParsePKCS1PrivateKey(p.PrivateKeyBytes)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{fmt.Sprintf("Unable to parse CA's private RSA key: %s", err)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Unable to parse CA's private RSA key: %s", err)}
|
||||
}
|
||||
|
||||
case PKCS8Block:
|
||||
|
@ -365,12 +365,12 @@ func (p *ParsedCertBundle) getSigner() (crypto.Signer, error) {
|
|||
case *rsa.PrivateKey, *ecdsa.PrivateKey:
|
||||
return k.(crypto.Signer), nil
|
||||
default:
|
||||
return nil, errutil.UserError{"Found unknown private key type in pkcs#8 wrapping"}
|
||||
return nil, errutil.UserError{Err: "Found unknown private key type in pkcs#8 wrapping"}
|
||||
}
|
||||
}
|
||||
return nil, errutil.UserError{fmt.Sprintf("Failed to parse pkcs#8 key: %v", err)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Failed to parse pkcs#8 key: %v", err)}
|
||||
default:
|
||||
return nil, errutil.UserError{"Unable to determine type of private key; only RSA and EC are supported"}
|
||||
return nil, errutil.UserError{Err: "Unable to determine type of private key; only RSA and EC are supported"}
|
||||
}
|
||||
return signer, nil
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ func (p *ParsedCertBundle) SetParsedPrivateKey(privateKey crypto.Signer, private
|
|||
func getPKCS8Type(bs []byte) (PrivateKeyType, error) {
|
||||
k, err := x509.ParsePKCS8PrivateKey(bs)
|
||||
if err != nil {
|
||||
return UnknownPrivateKey, errutil.UserError{fmt.Sprintf("Failed to parse pkcs#8 key: %v", err)}
|
||||
return UnknownPrivateKey, errutil.UserError{Err: fmt.Sprintf("Failed to parse pkcs#8 key: %v", err)}
|
||||
}
|
||||
|
||||
switch k.(type) {
|
||||
|
@ -394,7 +394,7 @@ func getPKCS8Type(bs []byte) (PrivateKeyType, error) {
|
|||
case *rsa.PrivateKey:
|
||||
return RSAPrivateKey, nil
|
||||
default:
|
||||
return UnknownPrivateKey, errutil.UserError{"Found unknown private key type in pkcs#8 wrapping"}
|
||||
return UnknownPrivateKey, errutil.UserError{Err: "Found unknown private key type in pkcs#8 wrapping"}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,7 +408,7 @@ func (c *CSRBundle) ToParsedCSRBundle() (*ParsedCSRBundle, error) {
|
|||
if len(c.PrivateKey) > 0 {
|
||||
pemBlock, _ = pem.Decode([]byte(c.PrivateKey))
|
||||
if pemBlock == nil {
|
||||
return nil, errutil.UserError{"Error decoding private key from cert bundle"}
|
||||
return nil, errutil.UserError{Err: "Error decoding private key from cert bundle"}
|
||||
}
|
||||
result.PrivateKeyBytes = pemBlock.Bytes
|
||||
|
||||
|
@ -426,25 +426,25 @@ func (c *CSRBundle) ToParsedCSRBundle() (*ParsedCSRBundle, error) {
|
|||
result.PrivateKeyType = RSAPrivateKey
|
||||
c.PrivateKeyType = "rsa"
|
||||
} else {
|
||||
return nil, errutil.UserError{fmt.Sprintf("Unknown private key type in bundle: %s", c.PrivateKeyType)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Unknown private key type in bundle: %s", c.PrivateKeyType)}
|
||||
}
|
||||
}
|
||||
|
||||
result.PrivateKey, err = result.getSigner()
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{fmt.Sprintf("Error getting signer: %s", err)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Error getting signer: %s", err)}
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.CSR) > 0 {
|
||||
pemBlock, _ = pem.Decode([]byte(c.CSR))
|
||||
if pemBlock == nil {
|
||||
return nil, errutil.UserError{"Error decoding certificate from cert bundle"}
|
||||
return nil, errutil.UserError{Err: "Error decoding certificate from cert bundle"}
|
||||
}
|
||||
result.CSRBytes = pemBlock.Bytes
|
||||
result.CSR, err = x509.ParseCertificateRequest(result.CSRBytes)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{fmt.Sprintf("Error encountered parsing certificate bytes from raw bundle: %v", err)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Error encountered parsing certificate bytes from raw bundle: %v", err)}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,7 +474,7 @@ func (p *ParsedCSRBundle) ToCSRBundle() (*CSRBundle, error) {
|
|||
result.PrivateKeyType = "ec"
|
||||
block.Type = "EC PRIVATE KEY"
|
||||
default:
|
||||
return nil, errutil.InternalError{"Could not determine private key type when creating block"}
|
||||
return nil, errutil.InternalError{Err: "Could not determine private key type when creating block"}
|
||||
}
|
||||
result.PrivateKey = strings.TrimSpace(string(pem.EncodeToMemory(&block)))
|
||||
}
|
||||
|
@ -491,24 +491,24 @@ func (p *ParsedCSRBundle) getSigner() (crypto.Signer, error) {
|
|||
var err error
|
||||
|
||||
if p.PrivateKeyBytes == nil || len(p.PrivateKeyBytes) == 0 {
|
||||
return nil, errutil.UserError{"Given parsed cert bundle does not have private key information"}
|
||||
return nil, errutil.UserError{Err: "Given parsed cert bundle does not have private key information"}
|
||||
}
|
||||
|
||||
switch p.PrivateKeyType {
|
||||
case ECPrivateKey:
|
||||
signer, err = x509.ParseECPrivateKey(p.PrivateKeyBytes)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{fmt.Sprintf("Unable to parse CA's private EC key: %s", err)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Unable to parse CA's private EC key: %s", err)}
|
||||
}
|
||||
|
||||
case RSAPrivateKey:
|
||||
signer, err = x509.ParsePKCS1PrivateKey(p.PrivateKeyBytes)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{fmt.Sprintf("Unable to parse CA's private RSA key: %s", err)}
|
||||
return nil, errutil.UserError{Err: fmt.Sprintf("Unable to parse CA's private RSA key: %s", err)}
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, errutil.UserError{"Unable to determine type of private key; only RSA and EC are supported"}
|
||||
return nil, errutil.UserError{Err: "Unable to determine type of private key; only RSA and EC are supported"}
|
||||
}
|
||||
return signer, nil
|
||||
}
|
||||
|
|
|
@ -953,8 +953,6 @@ func (p *Policy) VerifySignature(context, input []byte, sig, algorithm string) (
|
|||
default:
|
||||
return false, errutil.InternalError{Err: fmt.Sprintf("unsupported key type %v", p.Type)}
|
||||
}
|
||||
|
||||
return false, errutil.InternalError{Err: "no valid key type found"}
|
||||
}
|
||||
|
||||
func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) error {
|
||||
|
|
|
@ -36,7 +36,7 @@ func (p *ProxyProtoConfig) SetAuthorizedAddrs(addrs interface{}) error {
|
|||
for _, v := range addrs.([]interface{}) {
|
||||
stringAddr, ok := v.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("error parsing %q as string")
|
||||
return fmt.Errorf("error parsing %v as string", v)
|
||||
}
|
||||
stringAddrs = append(stringAddrs, stringAddr)
|
||||
}
|
||||
|
|
|
@ -349,7 +349,7 @@ func TestGlobbedStringsMatch(t *testing.T) {
|
|||
actual := GlobbedStringsMatch(tc.item, tc.val)
|
||||
|
||||
if actual != tc.expect {
|
||||
t.Fatalf("Bad testcase %#v, expected %b, got %b", tc, tc.expect, actual)
|
||||
t.Fatalf("Bad testcase %#v, expected %t, got %t", tc, tc.expect, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ type ResponseWrapInfo struct {
|
|||
|
||||
// WrappedEntityID is the entity identifier of the caller who initiated the
|
||||
// wrapping request
|
||||
WrappedEntityID string `json:"wrapped_entity_id" structs:"wrapped_entity_id" mapstructure:"wrapped_entity_id sentinel:"""`
|
||||
WrappedEntityID string `json:"wrapped_entity_id" structs:"wrapped_entity_id" mapstructure:"wrapped_entity_id" sentinel:""`
|
||||
|
||||
// The format to use. This doesn't get returned, it's only internal.
|
||||
Format string `json:"format" structs:"format" mapstructure:"format" sentinel:""`
|
||||
|
|
|
@ -122,7 +122,7 @@ func TestHTTP_Wrapping(t *testing.T) {
|
|||
t.Fatalf("mistmatched ttls: %d vs %d", creationTTL, wrapInfo.TTL)
|
||||
}
|
||||
if secret.Data["creation_time"].(string) != wrapInfo.CreationTime.Format(time.RFC3339Nano) {
|
||||
t.Fatalf("mistmatched creation times: %d vs %d", secret.Data["creation_time"].(string), wrapInfo.CreationTime.Format(time.RFC3339Nano))
|
||||
t.Fatalf("mistmatched creation times: %q vs %q", secret.Data["creation_time"].(string), wrapInfo.CreationTime.Format(time.RFC3339Nano))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,7 +310,7 @@ func TestHTTP_Wrapping(t *testing.T) {
|
|||
|
||||
// Check for correct CreationPath before rewrap
|
||||
if wrapInfo.CreationPath != "secret/foo" {
|
||||
t.Fatal("error on wrapInfo.CreationPath: expected: secret/foo, got: %s", wrapInfo.CreationPath)
|
||||
t.Fatalf("error on wrapInfo.CreationPath: expected: secret/foo, got: %s", wrapInfo.CreationPath)
|
||||
}
|
||||
|
||||
// Test rewrapping
|
||||
|
@ -323,7 +323,7 @@ func TestHTTP_Wrapping(t *testing.T) {
|
|||
|
||||
// Check for correct Creation path after rewrap
|
||||
if wrapInfo.CreationPath != "secret/foo" {
|
||||
t.Fatal("error on wrapInfo.CreationPath: expected: secret/foo, got: %s", wrapInfo.CreationPath)
|
||||
t.Fatalf("error on wrapInfo.CreationPath: expected: secret/foo, got: %s", wrapInfo.CreationPath)
|
||||
}
|
||||
|
||||
// Should be expired and fail
|
||||
|
|
|
@ -271,7 +271,7 @@ func testSalting(t *testing.T, ctx context.Context, storage logical.Storage, sal
|
|||
Value: []byte(`{"foo": "bar"}`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("err: %v", err)
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
// A read should transparently upgrade
|
||||
resp, err = b.HandleRequest(ctx, &logical.Request{
|
||||
|
|
|
@ -143,7 +143,7 @@ func testBackend(t *testing.T) (logical.Backend, func()) {
|
|||
Factory: mock.Factory,
|
||||
},
|
||||
}
|
||||
client, _ := gplugin.TestPluginRPCConn(t, pluginMap)
|
||||
client, _ := gplugin.TestPluginRPCConn(t, pluginMap, nil)
|
||||
cleanup := func() {
|
||||
client.Close()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var largeMsgGRPCCallOpts []grpc.CallOption = []grpc.CallOption{
|
||||
grpc.MaxCallSendMsgSize(math.MaxInt32),
|
||||
grpc.MaxCallRecvMsgSize(math.MaxInt32),
|
||||
}
|
|
@ -53,7 +53,7 @@ func (b *backendGRPCPluginClient) HandleRequest(ctx context.Context, req *logica
|
|||
|
||||
reply, err := b.client.HandleRequest(ctx, &pb.HandleRequestArgs{
|
||||
Request: protoReq,
|
||||
})
|
||||
}, largeMsgGRPCCallOpts...)
|
||||
if err != nil {
|
||||
if b.doneCtx.Err() != nil {
|
||||
return nil, ErrPluginShutdown
|
||||
|
@ -115,7 +115,7 @@ func (b *backendGRPCPluginClient) HandleExistenceCheck(ctx context.Context, req
|
|||
defer cancel()
|
||||
reply, err := b.client.HandleExistenceCheck(ctx, &pb.HandleExistenceCheckArgs{
|
||||
Request: protoReq,
|
||||
})
|
||||
}, largeMsgGRPCCallOpts...)
|
||||
if err != nil {
|
||||
if b.doneCtx.Err() != nil {
|
||||
return false, false, ErrPluginShutdown
|
||||
|
|
|
@ -25,7 +25,7 @@ type GRPCStorageClient struct {
|
|||
func (s *GRPCStorageClient) List(ctx context.Context, prefix string) ([]string, error) {
|
||||
reply, err := s.client.List(ctx, &pb.StorageListArgs{
|
||||
Prefix: prefix,
|
||||
})
|
||||
}, largeMsgGRPCCallOpts...)
|
||||
if err != nil {
|
||||
return reply.Keys, err
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ func (s *GRPCStorageClient) List(ctx context.Context, prefix string) ([]string,
|
|||
func (s *GRPCStorageClient) Get(ctx context.Context, key string) (*logical.StorageEntry, error) {
|
||||
reply, err := s.client.Get(ctx, &pb.StorageGetArgs{
|
||||
Key: key,
|
||||
})
|
||||
}, largeMsgGRPCCallOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func (s *GRPCStorageClient) Get(ctx context.Context, key string) (*logical.Stora
|
|||
func (s *GRPCStorageClient) Put(ctx context.Context, entry *logical.StorageEntry) error {
|
||||
reply, err := s.client.Put(ctx, &pb.StoragePutArgs{
|
||||
Entry: pb.LogicalStorageEntryToProtoStorageEntry(entry),
|
||||
})
|
||||
}, largeMsgGRPCCallOpts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -123,6 +123,15 @@ func (s *gRPCSystemViewClient) MlockEnabled() bool {
|
|||
return reply.Enabled
|
||||
}
|
||||
|
||||
func (s *gRPCSystemViewClient) LocalMount() bool {
|
||||
reply, err := s.client.LocalMount(context.Background(), &pb.Empty{})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return reply.Local
|
||||
}
|
||||
|
||||
type gRPCSystemViewServer struct {
|
||||
impl logical.SystemView
|
||||
}
|
||||
|
@ -200,3 +209,10 @@ func (s *gRPCSystemViewServer) MlockEnabled(ctx context.Context, _ *pb.Empty) (*
|
|||
Enabled: enabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *gRPCSystemViewServer) LocalMount(ctx context.Context, _ *pb.Empty) (*pb.LocalMountReply, error) {
|
||||
local := s.impl.LocalMount()
|
||||
return &pb.LocalMountReply{
|
||||
Local: local,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ It has these top-level messages:
|
|||
ResponseWrapDataArgs
|
||||
ResponseWrapDataReply
|
||||
MlockEnabledReply
|
||||
LocalMountReply
|
||||
*/
|
||||
package pb
|
||||
|
||||
|
@ -1384,6 +1385,22 @@ func (m *MlockEnabledReply) GetEnabled() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
type LocalMountReply struct {
|
||||
Local bool `sentinel:"" protobuf:"varint,1,opt,name=local" json:"local,omitempty"`
|
||||
}
|
||||
|
||||
func (m *LocalMountReply) Reset() { *m = LocalMountReply{} }
|
||||
func (m *LocalMountReply) String() string { return proto.CompactTextString(m) }
|
||||
func (*LocalMountReply) ProtoMessage() {}
|
||||
func (*LocalMountReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} }
|
||||
|
||||
func (m *LocalMountReply) GetLocal() bool {
|
||||
if m != nil {
|
||||
return m.Local
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Empty)(nil), "pb.Empty")
|
||||
proto.RegisterType((*Header)(nil), "pb.Header")
|
||||
|
@ -1424,6 +1441,7 @@ func init() {
|
|||
proto.RegisterType((*ResponseWrapDataArgs)(nil), "pb.ResponseWrapDataArgs")
|
||||
proto.RegisterType((*ResponseWrapDataReply)(nil), "pb.ResponseWrapDataReply")
|
||||
proto.RegisterType((*MlockEnabledReply)(nil), "pb.MlockEnabledReply")
|
||||
proto.RegisterType((*LocalMountReply)(nil), "pb.LocalMountReply")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
@ -1870,6 +1888,7 @@ type SystemViewClient interface {
|
|||
ReplicationState(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ReplicationStateReply, error)
|
||||
ResponseWrapData(ctx context.Context, in *ResponseWrapDataArgs, opts ...grpc.CallOption) (*ResponseWrapDataReply, error)
|
||||
MlockEnabled(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*MlockEnabledReply, error)
|
||||
LocalMount(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*LocalMountReply, error)
|
||||
}
|
||||
|
||||
type systemViewClient struct {
|
||||
|
@ -1952,6 +1971,15 @@ func (c *systemViewClient) MlockEnabled(ctx context.Context, in *Empty, opts ...
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *systemViewClient) LocalMount(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*LocalMountReply, error) {
|
||||
out := new(LocalMountReply)
|
||||
err := grpc.Invoke(ctx, "/pb.SystemView/LocalMount", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for SystemView service
|
||||
|
||||
type SystemViewServer interface {
|
||||
|
@ -1963,6 +1991,7 @@ type SystemViewServer interface {
|
|||
ReplicationState(context.Context, *Empty) (*ReplicationStateReply, error)
|
||||
ResponseWrapData(context.Context, *ResponseWrapDataArgs) (*ResponseWrapDataReply, error)
|
||||
MlockEnabled(context.Context, *Empty) (*MlockEnabledReply, error)
|
||||
LocalMount(context.Context, *Empty) (*LocalMountReply, error)
|
||||
}
|
||||
|
||||
func RegisterSystemViewServer(s *grpc.Server, srv SystemViewServer) {
|
||||
|
@ -2113,6 +2142,24 @@ func _SystemView_MlockEnabled_Handler(srv interface{}, ctx context.Context, dec
|
|||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SystemView_LocalMount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SystemViewServer).LocalMount(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/pb.SystemView/LocalMount",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SystemViewServer).LocalMount(ctx, req.(*Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _SystemView_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "pb.SystemView",
|
||||
HandlerType: (*SystemViewServer)(nil),
|
||||
|
@ -2149,6 +2196,10 @@ var _SystemView_serviceDesc = grpc.ServiceDesc{
|
|||
MethodName: "MlockEnabled",
|
||||
Handler: _SystemView_MlockEnabled_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "LocalMount",
|
||||
Handler: _SystemView_LocalMount_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "logical/plugin/pb/backend.proto",
|
||||
|
@ -2157,131 +2208,133 @@ var _SystemView_serviceDesc = grpc.ServiceDesc{
|
|||
func init() { proto.RegisterFile("logical/plugin/pb/backend.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 2014 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0xdb, 0x72, 0xdb, 0xc8,
|
||||
0xd1, 0x2e, 0x92, 0x22, 0x09, 0x36, 0x49, 0x1d, 0x46, 0xb2, 0x7f, 0x88, 0xf6, 0xfe, 0x62, 0xb0,
|
||||
0x65, 0x85, 0xeb, 0xaa, 0xa5, 0x6c, 0xe6, 0xe4, 0x4d, 0x6a, 0x37, 0xa5, 0xc8, 0x5a, 0xaf, 0xb2,
|
||||
0xf6, 0xae, 0x0a, 0x62, 0xb2, 0x49, 0x25, 0x55, 0xdc, 0x11, 0xd0, 0xa2, 0x50, 0x02, 0x01, 0x64,
|
||||
0x30, 0x90, 0xcc, 0xab, 0x3c, 0x42, 0xee, 0x36, 0x4f, 0x92, 0x77, 0x48, 0x55, 0xae, 0xf3, 0x1a,
|
||||
0xb9, 0xc8, 0x13, 0xa4, 0xe6, 0x00, 0x70, 0x40, 0x52, 0xb1, 0x53, 0x95, 0xdc, 0x4d, 0x7f, 0xdd,
|
||||
0x33, 0x3d, 0xd3, 0xd3, 0xfd, 0xf5, 0x00, 0x70, 0x10, 0xc6, 0xd3, 0xc0, 0xa3, 0xe1, 0x51, 0x12,
|
||||
0x66, 0xd3, 0x20, 0x3a, 0x4a, 0x2e, 0x8f, 0x2e, 0xa9, 0x77, 0x83, 0x91, 0x3f, 0x4c, 0x58, 0xcc,
|
||||
0x63, 0x52, 0x4d, 0x2e, 0x7b, 0x07, 0xd3, 0x38, 0x9e, 0x86, 0x78, 0x24, 0x91, 0xcb, 0xec, 0xea,
|
||||
0x88, 0x07, 0x33, 0x4c, 0x39, 0x9d, 0x25, 0xca, 0xc8, 0x69, 0x42, 0xfd, 0x74, 0x96, 0xf0, 0xb9,
|
||||
0xd3, 0x87, 0xc6, 0x17, 0x48, 0x7d, 0x64, 0xe4, 0x21, 0x34, 0xae, 0xe5, 0xc8, 0xae, 0xf4, 0x6b,
|
||||
0x83, 0x96, 0xab, 0x25, 0xe7, 0x77, 0x00, 0xe7, 0x62, 0xce, 0x29, 0x63, 0x31, 0x23, 0xfb, 0x60,
|
||||
0x21, 0x63, 0x13, 0x3e, 0x4f, 0xd0, 0xae, 0xf4, 0x2b, 0x83, 0xae, 0xdb, 0x44, 0xc6, 0xc6, 0xf3,
|
||||
0x04, 0xc9, 0xff, 0x81, 0x18, 0x4e, 0x66, 0xe9, 0xd4, 0xae, 0xf6, 0x2b, 0x62, 0x05, 0x64, 0xec,
|
||||
0x4d, 0x3a, 0xcd, 0xe7, 0x78, 0xb1, 0x8f, 0x76, 0xad, 0x5f, 0x19, 0xd4, 0xe4, 0x9c, 0x93, 0xd8,
|
||||
0x47, 0xe7, 0xbb, 0x0a, 0xd4, 0xcf, 0x29, 0xbf, 0x4e, 0x09, 0x81, 0x0d, 0x16, 0xc7, 0x5c, 0x3b,
|
||||
0x97, 0x63, 0x32, 0x80, 0xad, 0x2c, 0xa2, 0x19, 0xbf, 0xc6, 0x88, 0x07, 0x1e, 0xe5, 0xe8, 0xdb,
|
||||
0x55, 0xa9, 0x5e, 0x86, 0xc9, 0x87, 0xd0, 0x0d, 0x63, 0x8f, 0x86, 0x93, 0x94, 0xc7, 0x8c, 0x4e,
|
||||
0x85, 0x1f, 0x61, 0xd7, 0x91, 0xe0, 0x85, 0xc2, 0xc8, 0x53, 0xd8, 0x49, 0x91, 0x86, 0x93, 0x3b,
|
||||
0x46, 0x93, 0xc2, 0x70, 0x43, 0x2d, 0x28, 0x14, 0xdf, 0x30, 0x9a, 0x68, 0x5b, 0xe7, 0x4f, 0x0d,
|
||||
0x68, 0xba, 0xf8, 0x87, 0x0c, 0x53, 0x4e, 0x36, 0xa1, 0x1a, 0xf8, 0xf2, 0xb4, 0x2d, 0xb7, 0x1a,
|
||||
0xf8, 0x64, 0x08, 0xc4, 0xc5, 0x24, 0x14, 0xae, 0x83, 0x38, 0x3a, 0x09, 0xb3, 0x94, 0x23, 0xd3,
|
||||
0x67, 0x5e, 0xa3, 0x21, 0x8f, 0xa1, 0x15, 0x27, 0xc8, 0x24, 0x26, 0x03, 0xd0, 0x72, 0x17, 0x80,
|
||||
0x38, 0x78, 0x42, 0xf9, 0xb5, 0xbd, 0x21, 0x15, 0x72, 0x2c, 0x30, 0x9f, 0x72, 0x6a, 0xd7, 0x15,
|
||||
0x26, 0xc6, 0xc4, 0x81, 0x46, 0x8a, 0x1e, 0x43, 0x6e, 0x37, 0xfa, 0x95, 0x41, 0x7b, 0x04, 0xc3,
|
||||
0xe4, 0x72, 0x78, 0x21, 0x11, 0x57, 0x6b, 0xc8, 0x63, 0xd8, 0x10, 0x71, 0xb1, 0x9b, 0xd2, 0xc2,
|
||||
0x12, 0x16, 0xc7, 0x19, 0xbf, 0x76, 0x25, 0x4a, 0x46, 0xd0, 0x54, 0x77, 0x9a, 0xda, 0x56, 0xbf,
|
||||
0x36, 0x68, 0x8f, 0x6c, 0x61, 0xa0, 0x4f, 0x39, 0x54, 0x69, 0x90, 0x9e, 0x46, 0x9c, 0xcd, 0xdd,
|
||||
0xdc, 0x90, 0x7c, 0x0f, 0x3a, 0x5e, 0x18, 0x60, 0xc4, 0x27, 0x3c, 0xbe, 0xc1, 0xc8, 0x6e, 0xc9,
|
||||
0x1d, 0xb5, 0x15, 0x36, 0x16, 0x10, 0x19, 0xc1, 0x03, 0xd3, 0x64, 0x42, 0x3d, 0x0f, 0xd3, 0x34,
|
||||
0x66, 0x36, 0x48, 0xdb, 0x5d, 0xc3, 0xf6, 0x58, 0xab, 0xc4, 0xb2, 0x7e, 0x90, 0x26, 0x21, 0x9d,
|
||||
0x4f, 0x22, 0x3a, 0x43, 0xbb, 0xad, 0x96, 0xd5, 0xd8, 0x57, 0x74, 0x86, 0xe4, 0x00, 0xda, 0xb3,
|
||||
0x38, 0x8b, 0xf8, 0x24, 0x89, 0x83, 0x88, 0xdb, 0x1d, 0x69, 0x01, 0x12, 0x3a, 0x17, 0x08, 0xf9,
|
||||
0x00, 0x94, 0xa4, 0x92, 0xb1, 0xab, 0xe2, 0x2a, 0x11, 0x99, 0x8e, 0x4f, 0x60, 0x53, 0xa9, 0x8b,
|
||||
0xfd, 0x6c, 0x4a, 0x93, 0xae, 0x44, 0x8b, 0x9d, 0x3c, 0x83, 0x96, 0xcc, 0x87, 0x20, 0xba, 0x8a,
|
||||
0xed, 0x2d, 0x19, 0xb7, 0x5d, 0x23, 0x2c, 0x22, 0x27, 0xce, 0xa2, 0xab, 0xd8, 0xb5, 0xee, 0xf4,
|
||||
0x88, 0x7c, 0x0a, 0x8f, 0x4a, 0xe7, 0x65, 0x38, 0xa3, 0x41, 0x14, 0x44, 0xd3, 0x49, 0x96, 0x62,
|
||||
0x6a, 0x6f, 0xcb, 0x0c, 0xb7, 0x8d, 0x53, 0xbb, 0xb9, 0xc1, 0xaf, 0x52, 0x4c, 0xc9, 0x23, 0x68,
|
||||
0x89, 0xbc, 0xe5, 0xf3, 0x49, 0xe0, 0xdb, 0x3b, 0x72, 0x4b, 0x96, 0x02, 0xce, 0x7c, 0xf2, 0x7d,
|
||||
0xd8, 0x4a, 0xe2, 0x30, 0xf0, 0xe6, 0x93, 0xf8, 0x16, 0x19, 0x0b, 0x7c, 0xb4, 0x49, 0xbf, 0x32,
|
||||
0xb0, 0xdc, 0x4d, 0x05, 0x7f, 0xad, 0xd1, 0x75, 0xa5, 0xb1, 0x2b, 0x0d, 0x97, 0xe1, 0xde, 0xe7,
|
||||
0xd0, 0x31, 0xaf, 0x96, 0x6c, 0x43, 0xed, 0x06, 0xe7, 0x3a, 0x9d, 0xc5, 0x90, 0xf4, 0xa1, 0x7e,
|
||||
0x4b, 0xc3, 0x0c, 0x65, 0x0a, 0xeb, 0xc4, 0x52, 0x53, 0x5c, 0xa5, 0xf8, 0x69, 0xf5, 0x45, 0xc5,
|
||||
0xa1, 0x50, 0x3f, 0x0e, 0x03, 0x9a, 0x2e, 0xc5, 0xbd, 0xf2, 0xee, 0xb8, 0x57, 0xd7, 0xc5, 0x9d,
|
||||
0xc0, 0x86, 0xbc, 0x79, 0x55, 0x0f, 0x72, 0xec, 0xfc, 0xb3, 0x06, 0x1b, 0x22, 0x5f, 0xc9, 0x8f,
|
||||
0xa0, 0x1b, 0x22, 0x4d, 0x71, 0x12, 0x27, 0xa2, 0x46, 0x52, 0xe9, 0xa5, 0x3d, 0xda, 0x16, 0x3b,
|
||||
0x7b, 0x2d, 0x14, 0x5f, 0x2b, 0xdc, 0xed, 0x84, 0x86, 0x24, 0x58, 0x20, 0x88, 0x38, 0xb2, 0x88,
|
||||
0x86, 0x13, 0x59, 0x3f, 0xca, 0x73, 0x27, 0x07, 0x5f, 0x8a, 0x3a, 0x5a, 0x4e, 0xbd, 0xda, 0x6a,
|
||||
0xea, 0xf5, 0xc0, 0x92, 0xe1, 0x0e, 0x30, 0xd5, 0xfc, 0x50, 0xc8, 0x64, 0x04, 0xd6, 0x0c, 0x39,
|
||||
0xd5, 0xe5, 0x29, 0xaa, 0xe8, 0x61, 0x5e, 0x66, 0xc3, 0x37, 0x5a, 0xa1, 0x6a, 0xa8, 0xb0, 0x5b,
|
||||
0x29, 0xa2, 0xc6, 0x6a, 0x11, 0xf5, 0xc0, 0x2a, 0xe2, 0xd5, 0x54, 0x49, 0x91, 0xcb, 0x82, 0x99,
|
||||
0x13, 0x64, 0x41, 0xec, 0xdb, 0x96, 0xcc, 0x2d, 0x2d, 0x09, 0x5e, 0x8d, 0xb2, 0x99, 0xca, 0xba,
|
||||
0x96, 0xe2, 0xd5, 0x28, 0x9b, 0xad, 0x26, 0x19, 0x2c, 0x25, 0xd9, 0x01, 0xd4, 0xa9, 0xb8, 0x49,
|
||||
0x59, 0x75, 0xed, 0x51, 0x4b, 0xee, 0x5f, 0x00, 0xae, 0xc2, 0xc9, 0x10, 0xba, 0x53, 0x16, 0x67,
|
||||
0xc9, 0x44, 0x8a, 0x98, 0xda, 0x1d, 0x79, 0x50, 0xc3, 0xb0, 0x23, 0xf5, 0xc7, 0x4a, 0xdd, 0xfb,
|
||||
0x19, 0x74, 0x4b, 0x47, 0x5f, 0x93, 0x63, 0x7b, 0x66, 0x8e, 0xb5, 0xcc, 0xbc, 0xfa, 0x73, 0x05,
|
||||
0x3a, 0xe6, 0x9d, 0x8a, 0xc9, 0xe3, 0xf1, 0x6b, 0x39, 0xb9, 0xe6, 0x8a, 0xa1, 0x20, 0x50, 0x86,
|
||||
0x11, 0xde, 0xd1, 0xcb, 0x50, 0x2d, 0x60, 0xb9, 0x0b, 0x40, 0x68, 0x83, 0xc8, 0x63, 0x38, 0xc3,
|
||||
0x88, 0xeb, 0xfe, 0xb2, 0x00, 0xc8, 0x27, 0x00, 0x41, 0x9a, 0x66, 0x38, 0x11, 0x2d, 0x50, 0x92,
|
||||
0x6c, 0x7b, 0xd4, 0x1b, 0xaa, 0xfe, 0x38, 0xcc, 0xfb, 0xe3, 0x70, 0x9c, 0xf7, 0x47, 0xb7, 0x25,
|
||||
0xad, 0x85, 0xec, 0xfc, 0x11, 0x1a, 0x8a, 0x5f, 0xff, 0xa7, 0xf9, 0xb8, 0x0f, 0x96, 0x5a, 0x3b,
|
||||
0xf0, 0x75, 0x2e, 0x36, 0xa5, 0x7c, 0xe6, 0x3b, 0x7f, 0xab, 0x80, 0xe5, 0x62, 0x9a, 0xc4, 0x51,
|
||||
0x8a, 0x06, 0xff, 0x57, 0xde, 0xc9, 0xff, 0xd5, 0xb5, 0xfc, 0x9f, 0x77, 0x95, 0x9a, 0xd1, 0x55,
|
||||
0x7a, 0x60, 0x31, 0xf4, 0x03, 0x86, 0x1e, 0xd7, 0x1d, 0xa8, 0x90, 0x85, 0xee, 0x8e, 0x32, 0x41,
|
||||
0x5c, 0xa9, 0x4c, 0xf5, 0x96, 0x5b, 0xc8, 0xe4, 0xb9, 0x49, 0x9b, 0xaa, 0x21, 0xed, 0x29, 0xda,
|
||||
0x54, 0xdb, 0x5d, 0xe5, 0x4d, 0xe7, 0xaf, 0x55, 0xd8, 0x5e, 0x56, 0xaf, 0xb9, 0xec, 0x3d, 0xa8,
|
||||
0xab, 0x2a, 0xd1, 0x99, 0xc2, 0x57, 0xea, 0xa3, 0xb6, 0x54, 0x1f, 0x3f, 0x87, 0xae, 0xc7, 0x50,
|
||||
0x76, 0xd3, 0xf7, 0xbd, 0xe5, 0x4e, 0x3e, 0x41, 0x40, 0xe4, 0x23, 0xd8, 0x16, 0xbb, 0x4c, 0xd0,
|
||||
0x5f, 0x90, 0x96, 0x6a, 0xbd, 0x5b, 0x1a, 0x2f, 0x68, 0xeb, 0x29, 0xec, 0xe4, 0xa6, 0x8b, 0x02,
|
||||
0x6b, 0x94, 0x6c, 0x4f, 0xf3, 0x3a, 0x7b, 0x08, 0x8d, 0xab, 0x98, 0xcd, 0x28, 0xd7, 0x15, 0xad,
|
||||
0x25, 0x91, 0x16, 0xc5, 0x7e, 0x65, 0xeb, 0xb7, 0x54, 0x5a, 0xe4, 0xa0, 0x78, 0x10, 0x89, 0x0a,
|
||||
0x2e, 0x1e, 0x2b, 0xb2, 0xba, 0x2d, 0xd7, 0xca, 0x1f, 0x29, 0xce, 0x6f, 0x60, 0x6b, 0xa9, 0x3f,
|
||||
0xad, 0x09, 0xe4, 0xc2, 0x7d, 0xb5, 0xe4, 0xbe, 0xb4, 0x72, 0x6d, 0x69, 0xe5, 0xdf, 0xc2, 0xce,
|
||||
0x17, 0x34, 0xf2, 0x43, 0xd4, 0xeb, 0x1f, 0xb3, 0xa9, 0x64, 0x7c, 0xfd, 0x5c, 0x9a, 0xe8, 0x87,
|
||||
0x50, 0xd7, 0x6d, 0x69, 0xe4, 0xcc, 0x27, 0x4f, 0xa0, 0xc9, 0x94, 0xb5, 0x4e, 0xbc, 0xb6, 0xd1,
|
||||
0x40, 0xdd, 0x5c, 0xe7, 0x7c, 0x0b, 0xa4, 0xb4, 0xb4, 0x78, 0x29, 0xcd, 0xc9, 0x40, 0x24, 0xa0,
|
||||
0x4a, 0x0a, 0x9d, 0xd8, 0x1d, 0x33, 0x8f, 0xdc, 0x42, 0x4b, 0xfa, 0x50, 0x43, 0xc6, 0xb4, 0x8b,
|
||||
0x4d, 0x61, 0xb4, 0x78, 0x97, 0xba, 0x42, 0xe5, 0xfc, 0x10, 0x76, 0x2e, 0x12, 0xf4, 0x02, 0x1a,
|
||||
0xca, 0x37, 0xa5, 0x72, 0x70, 0x00, 0x75, 0x11, 0xe4, 0xbc, 0x66, 0x25, 0x89, 0x29, 0xb5, 0xc2,
|
||||
0x9d, 0x6f, 0xc1, 0x56, 0xfb, 0x3a, 0x7d, 0x1b, 0xa4, 0x1c, 0x23, 0x0f, 0x4f, 0xae, 0xd1, 0xbb,
|
||||
0xf9, 0x2f, 0x9e, 0xfc, 0x16, 0xf6, 0xd7, 0x79, 0xc8, 0xf7, 0xd7, 0xf6, 0x84, 0x34, 0xb9, 0x8a,
|
||||
0xb3, 0x48, 0xf9, 0xb0, 0x5c, 0x90, 0xd0, 0xe7, 0x02, 0x11, 0xf7, 0x88, 0x62, 0x5e, 0xaa, 0xa9,
|
||||
0x4f, 0x4b, 0x79, 0x3c, 0x6a, 0xf7, 0xc7, 0xe3, 0xbb, 0x0a, 0xb4, 0x2e, 0x90, 0x67, 0x89, 0x3c,
|
||||
0xcb, 0x23, 0x68, 0x5d, 0xb2, 0xf8, 0x06, 0xd9, 0xe2, 0x28, 0x96, 0x02, 0xce, 0x7c, 0xf2, 0x1c,
|
||||
0x1a, 0x27, 0x71, 0x74, 0x15, 0x4c, 0xe5, 0x0b, 0xbb, 0x3d, 0xda, 0x57, 0xec, 0xa2, 0xe7, 0x0e,
|
||||
0x95, 0x4e, 0xf5, 0x35, 0x6d, 0xd8, 0xfb, 0x04, 0xda, 0x06, 0xfc, 0x1f, 0x71, 0xfe, 0xff, 0x03,
|
||||
0xc8, 0xb5, 0x55, 0x04, 0xb6, 0xd5, 0x41, 0xf4, 0x4c, 0xb1, 0xf1, 0x03, 0x68, 0x89, 0xb7, 0x84,
|
||||
0x52, 0x13, 0xd8, 0x30, 0x3e, 0x37, 0xe4, 0xd8, 0x79, 0x02, 0x3b, 0x67, 0xd1, 0x2d, 0x0d, 0x03,
|
||||
0x9f, 0x72, 0xfc, 0x12, 0xe7, 0xf2, 0x80, 0x2b, 0x3b, 0x70, 0x2e, 0xa0, 0xa3, 0x1f, 0xf4, 0xef,
|
||||
0xb5, 0xc7, 0x8e, 0xde, 0xe3, 0xbf, 0x2f, 0x91, 0x8f, 0x60, 0x4b, 0x2f, 0xfa, 0x3a, 0xd0, 0x05,
|
||||
0x22, 0x3a, 0x34, 0xc3, 0xab, 0xe0, 0xad, 0x5e, 0x5a, 0x4b, 0xce, 0x0b, 0xd8, 0x36, 0x4c, 0x8b,
|
||||
0xe3, 0xdc, 0xe0, 0x3c, 0xcd, 0x3f, 0x74, 0xc4, 0x38, 0x8f, 0x40, 0x75, 0x11, 0x01, 0x07, 0x36,
|
||||
0xf5, 0xcc, 0x57, 0xc8, 0xef, 0x39, 0xdd, 0x97, 0xc5, 0x46, 0x5e, 0xa1, 0x5e, 0xfc, 0x10, 0xea,
|
||||
0x28, 0x4e, 0x6a, 0x36, 0x28, 0x33, 0x02, 0xae, 0x52, 0xaf, 0x71, 0xf8, 0xa2, 0x70, 0x78, 0x9e,
|
||||
0x29, 0x87, 0xef, 0xb9, 0x96, 0xf3, 0x61, 0xb1, 0x8d, 0xf3, 0x8c, 0xdf, 0x77, 0xa3, 0x4f, 0x60,
|
||||
0x47, 0x1b, 0xbd, 0xc4, 0x10, 0x39, 0xde, 0x73, 0xa4, 0x43, 0x20, 0x25, 0xb3, 0xfb, 0x96, 0x7b,
|
||||
0x0c, 0xd6, 0x78, 0xfc, 0xba, 0xd0, 0x96, 0x99, 0xcf, 0xf9, 0x14, 0x76, 0x2e, 0x32, 0x3f, 0x3e,
|
||||
0x67, 0xc1, 0x6d, 0x10, 0xe2, 0x54, 0x39, 0xcb, 0xbf, 0xb3, 0x2a, 0xc6, 0x77, 0xd6, 0xda, 0x5e,
|
||||
0xe3, 0x0c, 0x80, 0x94, 0xa6, 0x17, 0xf7, 0x96, 0x66, 0x7e, 0xac, 0x0b, 0x54, 0x8e, 0x9d, 0x01,
|
||||
0x74, 0xc6, 0x54, 0x74, 0x73, 0x5f, 0xd9, 0xd8, 0xd0, 0xe4, 0x4a, 0xd6, 0x66, 0xb9, 0xe8, 0x8c,
|
||||
0x60, 0xef, 0x84, 0x7a, 0xd7, 0x41, 0x34, 0x7d, 0x19, 0xa4, 0xe2, 0xd9, 0xa2, 0x67, 0xf4, 0xc0,
|
||||
0xf2, 0x35, 0xa0, 0xa7, 0x14, 0xb2, 0xf3, 0x31, 0x3c, 0x30, 0xbe, 0x26, 0x2f, 0x38, 0xcd, 0xe3,
|
||||
0xb1, 0x07, 0xf5, 0x54, 0x48, 0x72, 0x46, 0xdd, 0x55, 0x82, 0xf3, 0x15, 0xec, 0x99, 0xed, 0x55,
|
||||
0x3c, 0x2e, 0xf2, 0x83, 0xcb, 0xb6, 0x5f, 0x31, 0xda, 0xbe, 0x8e, 0x59, 0x75, 0xd1, 0x2d, 0xb6,
|
||||
0xa1, 0xf6, 0xcb, 0x6f, 0xc6, 0x3a, 0xd9, 0xc5, 0xd0, 0xf9, 0xbd, 0x70, 0x5f, 0x5e, 0x4f, 0xb9,
|
||||
0x2f, 0xf5, 0xfe, 0xca, 0xfb, 0xf4, 0xfe, 0x35, 0xf9, 0xf6, 0x31, 0xec, 0xbc, 0x09, 0x63, 0xef,
|
||||
0xe6, 0x34, 0x32, 0xa2, 0x61, 0x43, 0x13, 0x23, 0x33, 0x18, 0xb9, 0x38, 0xfa, 0x47, 0x15, 0x9a,
|
||||
0xbf, 0x50, 0xff, 0x39, 0xc8, 0x67, 0xd0, 0x2d, 0x35, 0x12, 0xf2, 0x40, 0x7e, 0xb1, 0x2c, 0xb7,
|
||||
0xad, 0xde, 0xc3, 0x15, 0x58, 0x79, 0x79, 0x06, 0x1d, 0xb3, 0x4d, 0x10, 0xd9, 0x12, 0xe4, 0xef,
|
||||
0x90, 0x9e, 0x5c, 0x69, 0xb5, 0x87, 0x5c, 0xc0, 0xde, 0x3a, 0x02, 0x27, 0x8f, 0x17, 0x1e, 0x56,
|
||||
0x9b, 0x47, 0xef, 0x83, 0xfb, 0xb4, 0x39, 0xf1, 0x37, 0x4f, 0x42, 0xa4, 0x51, 0x96, 0x98, 0x3b,
|
||||
0x58, 0x0c, 0xc9, 0x73, 0xe8, 0x96, 0x48, 0x4e, 0x9d, 0x73, 0x85, 0xf7, 0xcc, 0x29, 0x87, 0x50,
|
||||
0x97, 0xc4, 0x4a, 0xba, 0x25, 0xfe, 0xee, 0x6d, 0x16, 0xa2, 0xf2, 0xdd, 0x87, 0x0d, 0xf9, 0xb1,
|
||||
0x66, 0x38, 0x96, 0x33, 0x0a, 0xd6, 0x1d, 0xfd, 0xbd, 0x02, 0xcd, 0xfc, 0xc7, 0xc9, 0x73, 0xd8,
|
||||
0x10, 0xfc, 0x45, 0x76, 0x0d, 0x0a, 0xc8, 0xb9, 0xaf, 0xb7, 0xb7, 0x04, 0x2a, 0x07, 0x43, 0xa8,
|
||||
0xbd, 0x42, 0x4e, 0x88, 0xa1, 0xd4, 0x44, 0xd6, 0xdb, 0x2d, 0x63, 0x85, 0xfd, 0x79, 0x56, 0xb6,
|
||||
0xd7, 0x3c, 0x54, 0xb2, 0x2f, 0x18, 0xe6, 0x27, 0xd0, 0x50, 0x0c, 0xa1, 0x82, 0xb2, 0xc2, 0x2d,
|
||||
0xea, 0xf2, 0x57, 0xb9, 0x64, 0xf4, 0x97, 0x1a, 0xc0, 0xc5, 0x3c, 0xe5, 0x38, 0xfb, 0x75, 0x80,
|
||||
0x77, 0xe4, 0x29, 0x6c, 0xbd, 0xc4, 0x2b, 0x9a, 0x85, 0x5c, 0xbe, 0xe3, 0x45, 0x25, 0x18, 0x31,
|
||||
0x91, 0x4f, 0x91, 0x82, 0x68, 0x0e, 0xa1, 0xfd, 0x86, 0xbe, 0x7d, 0xb7, 0xdd, 0x67, 0xd0, 0x2d,
|
||||
0xf1, 0x87, 0xde, 0xe2, 0x32, 0x23, 0xe9, 0x2d, 0xae, 0x32, 0xcd, 0x21, 0x34, 0x35, 0xab, 0x98,
|
||||
0x3e, 0x24, 0xff, 0x96, 0xd8, 0xe6, 0xc7, 0xb0, 0xb5, 0xc4, 0x29, 0xa6, 0xbd, 0xfc, 0xb9, 0xb3,
|
||||
0x96, 0x73, 0x5e, 0x88, 0x77, 0x78, 0x99, 0x57, 0xcc, 0x89, 0xfb, 0xaa, 0x96, 0xd7, 0x11, 0xcf,
|
||||
0xab, 0xf2, 0x0b, 0x5e, 0x7e, 0xbf, 0xd8, 0xcb, 0xa5, 0x9f, 0x13, 0x4f, 0xbe, 0xd0, 0x3a, 0x0a,
|
||||
0x79, 0x06, 0x1d, 0xb3, 0xfa, 0x57, 0x4a, 0x70, 0x85, 0x1a, 0x2e, 0x1b, 0xf2, 0x15, 0xff, 0x83,
|
||||
0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0x0c, 0x80, 0xb2, 0xf5, 0x00, 0x15, 0x00, 0x00,
|
||||
// 2042 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0x5f, 0x73, 0xdb, 0xc6,
|
||||
0x11, 0x1f, 0x92, 0x22, 0x09, 0x2e, 0x49, 0xfd, 0x39, 0xcb, 0x2e, 0x44, 0x3b, 0x15, 0x8b, 0x8c,
|
||||
0x15, 0xc6, 0xd3, 0x50, 0x36, 0xfb, 0xcf, 0x69, 0x27, 0xe9, 0xa8, 0xb2, 0xe2, 0xa8, 0x91, 0x12,
|
||||
0x0d, 0xa4, 0x36, 0xed, 0xb4, 0x33, 0xcc, 0x09, 0x58, 0x51, 0x18, 0x81, 0x00, 0x7a, 0x38, 0x48,
|
||||
0xe6, 0x53, 0x3f, 0x42, 0xdf, 0xd2, 0xaf, 0xd4, 0x99, 0x3e, 0xf7, 0x13, 0xf4, 0xbd, 0x0f, 0xfd,
|
||||
0x04, 0x9d, 0xfb, 0x03, 0xf0, 0x40, 0x52, 0xb5, 0x3b, 0xd3, 0xbc, 0xdd, 0xfe, 0x76, 0xef, 0xf6,
|
||||
0x6e, 0xb1, 0xfb, 0xdb, 0x3b, 0xc0, 0x6e, 0x18, 0x4f, 0x02, 0x8f, 0x86, 0xfb, 0x49, 0x98, 0x4d,
|
||||
0x82, 0x68, 0x3f, 0xb9, 0xdc, 0xbf, 0xa4, 0xde, 0x0d, 0x46, 0xfe, 0x30, 0x61, 0x31, 0x8f, 0x49,
|
||||
0x35, 0xb9, 0xec, 0xed, 0x4e, 0xe2, 0x78, 0x12, 0xe2, 0xbe, 0x44, 0x2e, 0xb3, 0xab, 0x7d, 0x1e,
|
||||
0x4c, 0x31, 0xe5, 0x74, 0x9a, 0x28, 0x23, 0xa7, 0x09, 0xf5, 0xa3, 0x69, 0xc2, 0x67, 0x4e, 0x1f,
|
||||
0x1a, 0x9f, 0x23, 0xf5, 0x91, 0x91, 0x47, 0xd0, 0xb8, 0x96, 0x23, 0xbb, 0xd2, 0xaf, 0x0d, 0x5a,
|
||||
0xae, 0x96, 0x9c, 0x3f, 0x00, 0x9c, 0x89, 0x39, 0x47, 0x8c, 0xc5, 0x8c, 0xec, 0x80, 0x85, 0x8c,
|
||||
0x8d, 0xf9, 0x2c, 0x41, 0xbb, 0xd2, 0xaf, 0x0c, 0xba, 0x6e, 0x13, 0x19, 0xbb, 0x98, 0x25, 0x48,
|
||||
0xbe, 0x07, 0x62, 0x38, 0x9e, 0xa6, 0x13, 0xbb, 0xda, 0xaf, 0x88, 0x15, 0x90, 0xb1, 0xd3, 0x74,
|
||||
0x92, 0xcf, 0xf1, 0x62, 0x1f, 0xed, 0x5a, 0xbf, 0x32, 0xa8, 0xc9, 0x39, 0x87, 0xb1, 0x8f, 0xce,
|
||||
0xb7, 0x15, 0xa8, 0x9f, 0x51, 0x7e, 0x9d, 0x12, 0x02, 0x6b, 0x2c, 0x8e, 0xb9, 0x76, 0x2e, 0xc7,
|
||||
0x64, 0x00, 0x1b, 0x59, 0x44, 0x33, 0x7e, 0x8d, 0x11, 0x0f, 0x3c, 0xca, 0xd1, 0xb7, 0xab, 0x52,
|
||||
0xbd, 0x08, 0x93, 0xf7, 0xa1, 0x1b, 0xc6, 0x1e, 0x0d, 0xc7, 0x29, 0x8f, 0x19, 0x9d, 0x08, 0x3f,
|
||||
0xc2, 0xae, 0x23, 0xc1, 0x73, 0x85, 0x91, 0x67, 0xb0, 0x95, 0x22, 0x0d, 0xc7, 0x77, 0x8c, 0x26,
|
||||
0x85, 0xe1, 0x9a, 0x5a, 0x50, 0x28, 0xbe, 0x66, 0x34, 0xd1, 0xb6, 0xce, 0x5f, 0x1a, 0xd0, 0x74,
|
||||
0xf1, 0x4f, 0x19, 0xa6, 0x9c, 0xac, 0x43, 0x35, 0xf0, 0xe5, 0x69, 0x5b, 0x6e, 0x35, 0xf0, 0xc9,
|
||||
0x10, 0x88, 0x8b, 0x49, 0x28, 0x5c, 0x07, 0x71, 0x74, 0x18, 0x66, 0x29, 0x47, 0xa6, 0xcf, 0xbc,
|
||||
0x42, 0x43, 0x9e, 0x40, 0x2b, 0x4e, 0x90, 0x49, 0x4c, 0x06, 0xa0, 0xe5, 0xce, 0x01, 0x71, 0xf0,
|
||||
0x84, 0xf2, 0x6b, 0x7b, 0x4d, 0x2a, 0xe4, 0x58, 0x60, 0x3e, 0xe5, 0xd4, 0xae, 0x2b, 0x4c, 0x8c,
|
||||
0x89, 0x03, 0x8d, 0x14, 0x3d, 0x86, 0xdc, 0x6e, 0xf4, 0x2b, 0x83, 0xf6, 0x08, 0x86, 0xc9, 0xe5,
|
||||
0xf0, 0x5c, 0x22, 0xae, 0xd6, 0x90, 0x27, 0xb0, 0x26, 0xe2, 0x62, 0x37, 0xa5, 0x85, 0x25, 0x2c,
|
||||
0x0e, 0x32, 0x7e, 0xed, 0x4a, 0x94, 0x8c, 0xa0, 0xa9, 0xbe, 0x69, 0x6a, 0x5b, 0xfd, 0xda, 0xa0,
|
||||
0x3d, 0xb2, 0x85, 0x81, 0x3e, 0xe5, 0x50, 0xa5, 0x41, 0x7a, 0x14, 0x71, 0x36, 0x73, 0x73, 0x43,
|
||||
0xf2, 0x03, 0xe8, 0x78, 0x61, 0x80, 0x11, 0x1f, 0xf3, 0xf8, 0x06, 0x23, 0xbb, 0x25, 0x77, 0xd4,
|
||||
0x56, 0xd8, 0x85, 0x80, 0xc8, 0x08, 0x1e, 0x9a, 0x26, 0x63, 0xea, 0x79, 0x98, 0xa6, 0x31, 0xb3,
|
||||
0x41, 0xda, 0x3e, 0x30, 0x6c, 0x0f, 0xb4, 0x4a, 0x2c, 0xeb, 0x07, 0x69, 0x12, 0xd2, 0xd9, 0x38,
|
||||
0xa2, 0x53, 0xb4, 0xdb, 0x6a, 0x59, 0x8d, 0x7d, 0x49, 0xa7, 0x48, 0x76, 0xa1, 0x3d, 0x8d, 0xb3,
|
||||
0x88, 0x8f, 0x93, 0x38, 0x88, 0xb8, 0xdd, 0x91, 0x16, 0x20, 0xa1, 0x33, 0x81, 0x90, 0xf7, 0x40,
|
||||
0x49, 0x2a, 0x19, 0xbb, 0x2a, 0xae, 0x12, 0x91, 0xe9, 0xf8, 0x14, 0xd6, 0x95, 0xba, 0xd8, 0xcf,
|
||||
0xba, 0x34, 0xe9, 0x4a, 0xb4, 0xd8, 0xc9, 0x73, 0x68, 0xc9, 0x7c, 0x08, 0xa2, 0xab, 0xd8, 0xde,
|
||||
0x90, 0x71, 0x7b, 0x60, 0x84, 0x45, 0xe4, 0xc4, 0x71, 0x74, 0x15, 0xbb, 0xd6, 0x9d, 0x1e, 0x91,
|
||||
0x4f, 0xe0, 0x71, 0xe9, 0xbc, 0x0c, 0xa7, 0x34, 0x88, 0x82, 0x68, 0x32, 0xce, 0x52, 0x4c, 0xed,
|
||||
0x4d, 0x99, 0xe1, 0xb6, 0x71, 0x6a, 0x37, 0x37, 0xf8, 0x4d, 0x8a, 0x29, 0x79, 0x0c, 0x2d, 0x91,
|
||||
0xb7, 0x7c, 0x36, 0x0e, 0x7c, 0x7b, 0x4b, 0x6e, 0xc9, 0x52, 0xc0, 0xb1, 0x4f, 0x3e, 0x80, 0x8d,
|
||||
0x24, 0x0e, 0x03, 0x6f, 0x36, 0x8e, 0x6f, 0x91, 0xb1, 0xc0, 0x47, 0x9b, 0xf4, 0x2b, 0x03, 0xcb,
|
||||
0x5d, 0x57, 0xf0, 0x57, 0x1a, 0x5d, 0x55, 0x1a, 0x0f, 0xa4, 0xe1, 0x22, 0xdc, 0xfb, 0x0c, 0x3a,
|
||||
0xe6, 0xa7, 0x25, 0x9b, 0x50, 0xbb, 0xc1, 0x99, 0x4e, 0x67, 0x31, 0x24, 0x7d, 0xa8, 0xdf, 0xd2,
|
||||
0x30, 0x43, 0x99, 0xc2, 0x3a, 0xb1, 0xd4, 0x14, 0x57, 0x29, 0x7e, 0x5e, 0x7d, 0x59, 0x71, 0x28,
|
||||
0xd4, 0x0f, 0xc2, 0x80, 0xa6, 0x0b, 0x71, 0xaf, 0xbc, 0x3d, 0xee, 0xd5, 0x55, 0x71, 0x27, 0xb0,
|
||||
0x26, 0xbf, 0xbc, 0xaa, 0x07, 0x39, 0x76, 0xfe, 0x5d, 0x83, 0x35, 0x91, 0xaf, 0xe4, 0x27, 0xd0,
|
||||
0x0d, 0x91, 0xa6, 0x38, 0x8e, 0x13, 0x51, 0x23, 0xa9, 0xf4, 0xd2, 0x1e, 0x6d, 0x8a, 0x9d, 0x9d,
|
||||
0x08, 0xc5, 0x57, 0x0a, 0x77, 0x3b, 0xa1, 0x21, 0x09, 0x16, 0x08, 0x22, 0x8e, 0x2c, 0xa2, 0xe1,
|
||||
0x58, 0xd6, 0x8f, 0xf2, 0xdc, 0xc9, 0xc1, 0x57, 0xa2, 0x8e, 0x16, 0x53, 0xaf, 0xb6, 0x9c, 0x7a,
|
||||
0x3d, 0xb0, 0x64, 0xb8, 0x03, 0x4c, 0x35, 0x3f, 0x14, 0x32, 0x19, 0x81, 0x35, 0x45, 0x4e, 0x75,
|
||||
0x79, 0x8a, 0x2a, 0x7a, 0x94, 0x97, 0xd9, 0xf0, 0x54, 0x2b, 0x54, 0x0d, 0x15, 0x76, 0x4b, 0x45,
|
||||
0xd4, 0x58, 0x2e, 0xa2, 0x1e, 0x58, 0x45, 0xbc, 0x9a, 0x2a, 0x29, 0x72, 0x59, 0x30, 0x73, 0x82,
|
||||
0x2c, 0x88, 0x7d, 0xdb, 0x92, 0xb9, 0xa5, 0x25, 0xc1, 0xab, 0x51, 0x36, 0x55, 0x59, 0xd7, 0x52,
|
||||
0xbc, 0x1a, 0x65, 0xd3, 0xe5, 0x24, 0x83, 0x85, 0x24, 0xdb, 0x85, 0x3a, 0x15, 0x5f, 0x52, 0x56,
|
||||
0x5d, 0x7b, 0xd4, 0x92, 0xfb, 0x17, 0x80, 0xab, 0x70, 0x32, 0x84, 0xee, 0x84, 0xc5, 0x59, 0x32,
|
||||
0x96, 0x22, 0xa6, 0x76, 0x47, 0x1e, 0xd4, 0x30, 0xec, 0x48, 0xfd, 0x81, 0x52, 0xf7, 0x7e, 0x01,
|
||||
0xdd, 0xd2, 0xd1, 0x57, 0xe4, 0xd8, 0xb6, 0x99, 0x63, 0x2d, 0x33, 0xaf, 0xfe, 0x5a, 0x81, 0x8e,
|
||||
0xf9, 0x4d, 0xc5, 0xe4, 0x8b, 0x8b, 0x13, 0x39, 0xb9, 0xe6, 0x8a, 0xa1, 0x20, 0x50, 0x86, 0x11,
|
||||
0xde, 0xd1, 0xcb, 0x50, 0x2d, 0x60, 0xb9, 0x73, 0x40, 0x68, 0x83, 0xc8, 0x63, 0x38, 0xc5, 0x88,
|
||||
0xeb, 0xfe, 0x32, 0x07, 0xc8, 0xc7, 0x00, 0x41, 0x9a, 0x66, 0x38, 0x16, 0x2d, 0x50, 0x92, 0x6c,
|
||||
0x7b, 0xd4, 0x1b, 0xaa, 0xfe, 0x38, 0xcc, 0xfb, 0xe3, 0xf0, 0x22, 0xef, 0x8f, 0x6e, 0x4b, 0x5a,
|
||||
0x0b, 0xd9, 0xf9, 0x33, 0x34, 0x14, 0xbf, 0x7e, 0xa7, 0xf9, 0xb8, 0x03, 0x96, 0x5a, 0x3b, 0xf0,
|
||||
0x75, 0x2e, 0x36, 0xa5, 0x7c, 0xec, 0x3b, 0x7f, 0xaf, 0x80, 0xe5, 0x62, 0x9a, 0xc4, 0x51, 0x8a,
|
||||
0x06, 0xff, 0x57, 0xde, 0xca, 0xff, 0xd5, 0x95, 0xfc, 0x9f, 0x77, 0x95, 0x9a, 0xd1, 0x55, 0x7a,
|
||||
0x60, 0x31, 0xf4, 0x03, 0x86, 0x1e, 0xd7, 0x1d, 0xa8, 0x90, 0x85, 0xee, 0x8e, 0x32, 0x41, 0x5c,
|
||||
0xa9, 0x4c, 0xf5, 0x96, 0x5b, 0xc8, 0xe4, 0x85, 0x49, 0x9b, 0xaa, 0x21, 0x6d, 0x2b, 0xda, 0x54,
|
||||
0xdb, 0x5d, 0xe6, 0x4d, 0xe7, 0x6f, 0x55, 0xd8, 0x5c, 0x54, 0xaf, 0xf8, 0xd8, 0xdb, 0x50, 0x57,
|
||||
0x55, 0xa2, 0x33, 0x85, 0x2f, 0xd5, 0x47, 0x6d, 0xa1, 0x3e, 0x7e, 0x09, 0x5d, 0x8f, 0xa1, 0xec,
|
||||
0xa6, 0xef, 0xfa, 0x95, 0x3b, 0xf9, 0x04, 0x01, 0x91, 0x0f, 0x61, 0x53, 0xec, 0x32, 0x41, 0x7f,
|
||||
0x4e, 0x5a, 0xaa, 0xf5, 0x6e, 0x68, 0xbc, 0xa0, 0xad, 0x67, 0xb0, 0x95, 0x9b, 0xce, 0x0b, 0xac,
|
||||
0x51, 0xb2, 0x3d, 0xca, 0xeb, 0xec, 0x11, 0x34, 0xae, 0x62, 0x36, 0xa5, 0x5c, 0x57, 0xb4, 0x96,
|
||||
0x44, 0x5a, 0x14, 0xfb, 0x95, 0xad, 0xdf, 0x52, 0x69, 0x91, 0x83, 0xe2, 0x42, 0x24, 0x2a, 0xb8,
|
||||
0xb8, 0xac, 0xc8, 0xea, 0xb6, 0x5c, 0x2b, 0xbf, 0xa4, 0x38, 0xbf, 0x83, 0x8d, 0x85, 0xfe, 0xb4,
|
||||
0x22, 0x90, 0x73, 0xf7, 0xd5, 0x92, 0xfb, 0xd2, 0xca, 0xb5, 0x85, 0x95, 0x7f, 0x0f, 0x5b, 0x9f,
|
||||
0xd3, 0xc8, 0x0f, 0x51, 0xaf, 0x7f, 0xc0, 0x26, 0x92, 0xf1, 0xf5, 0x75, 0x69, 0xac, 0x2f, 0x42,
|
||||
0x5d, 0xb7, 0xa5, 0x91, 0x63, 0x9f, 0x3c, 0x85, 0x26, 0x53, 0xd6, 0x3a, 0xf1, 0xda, 0x46, 0x03,
|
||||
0x75, 0x73, 0x9d, 0xf3, 0x0d, 0x90, 0xd2, 0xd2, 0xe2, 0xa6, 0x34, 0x23, 0x03, 0x91, 0x80, 0x2a,
|
||||
0x29, 0x74, 0x62, 0x77, 0xcc, 0x3c, 0x72, 0x0b, 0x2d, 0xe9, 0x43, 0x0d, 0x19, 0xd3, 0x2e, 0xd6,
|
||||
0x85, 0xd1, 0xfc, 0x5e, 0xea, 0x0a, 0x95, 0xf3, 0x63, 0xd8, 0x3a, 0x4f, 0xd0, 0x0b, 0x68, 0x28,
|
||||
0xef, 0x94, 0xca, 0xc1, 0x2e, 0xd4, 0x45, 0x90, 0xf3, 0x9a, 0x95, 0x24, 0xa6, 0xd4, 0x0a, 0x77,
|
||||
0xbe, 0x01, 0x5b, 0xed, 0xeb, 0xe8, 0x4d, 0x90, 0x72, 0x8c, 0x3c, 0x3c, 0xbc, 0x46, 0xef, 0xe6,
|
||||
0xff, 0x78, 0xf2, 0x5b, 0xd8, 0x59, 0xe5, 0x21, 0xdf, 0x5f, 0xdb, 0x13, 0xd2, 0xf8, 0x2a, 0xce,
|
||||
0x22, 0xe5, 0xc3, 0x72, 0x41, 0x42, 0x9f, 0x09, 0x44, 0x7c, 0x47, 0x14, 0xf3, 0x52, 0x4d, 0x7d,
|
||||
0x5a, 0xca, 0xe3, 0x51, 0xbb, 0x3f, 0x1e, 0xdf, 0x56, 0xa0, 0x75, 0x8e, 0x3c, 0x4b, 0xe4, 0x59,
|
||||
0x1e, 0x43, 0xeb, 0x92, 0xc5, 0x37, 0xc8, 0xe6, 0x47, 0xb1, 0x14, 0x70, 0xec, 0x93, 0x17, 0xd0,
|
||||
0x38, 0x8c, 0xa3, 0xab, 0x60, 0x22, 0x6f, 0xd8, 0xed, 0xd1, 0x8e, 0x62, 0x17, 0x3d, 0x77, 0xa8,
|
||||
0x74, 0xaa, 0xaf, 0x69, 0xc3, 0xde, 0xc7, 0xd0, 0x36, 0xe0, 0xff, 0x89, 0xf3, 0xbf, 0x0f, 0x20,
|
||||
0xd7, 0x56, 0x11, 0xd8, 0x54, 0x07, 0xd1, 0x33, 0xc5, 0xc6, 0x77, 0xa1, 0x25, 0xee, 0x12, 0x4a,
|
||||
0x4d, 0x60, 0xcd, 0x78, 0x6e, 0xc8, 0xb1, 0xf3, 0x14, 0xb6, 0x8e, 0xa3, 0x5b, 0x1a, 0x06, 0x3e,
|
||||
0xe5, 0xf8, 0x05, 0xce, 0xe4, 0x01, 0x97, 0x76, 0xe0, 0x9c, 0x43, 0x47, 0x5f, 0xe8, 0xdf, 0x69,
|
||||
0x8f, 0x1d, 0xbd, 0xc7, 0xff, 0x5e, 0x22, 0x1f, 0xc2, 0x86, 0x5e, 0xf4, 0x24, 0xd0, 0x05, 0x22,
|
||||
0x3a, 0x34, 0xc3, 0xab, 0xe0, 0x8d, 0x5e, 0x5a, 0x4b, 0xce, 0x4b, 0xd8, 0x34, 0x4c, 0x8b, 0xe3,
|
||||
0xdc, 0xe0, 0x2c, 0xcd, 0x1f, 0x3a, 0x62, 0x9c, 0x47, 0xa0, 0x3a, 0x8f, 0x80, 0x03, 0xeb, 0x7a,
|
||||
0xe6, 0x6b, 0xe4, 0xf7, 0x9c, 0xee, 0x8b, 0x62, 0x23, 0xaf, 0x51, 0x2f, 0xbe, 0x07, 0x75, 0x14,
|
||||
0x27, 0x35, 0x1b, 0x94, 0x19, 0x01, 0x57, 0xa9, 0x57, 0x38, 0x7c, 0x59, 0x38, 0x3c, 0xcb, 0x94,
|
||||
0xc3, 0x77, 0x5c, 0xcb, 0x79, 0xbf, 0xd8, 0xc6, 0x59, 0xc6, 0xef, 0xfb, 0xa2, 0x4f, 0x61, 0x4b,
|
||||
0x1b, 0xbd, 0xc2, 0x10, 0x39, 0xde, 0x73, 0xa4, 0x3d, 0x20, 0x25, 0xb3, 0xfb, 0x96, 0x7b, 0x02,
|
||||
0xd6, 0xc5, 0xc5, 0x49, 0xa1, 0x2d, 0x33, 0x9f, 0xf3, 0x09, 0x6c, 0x9d, 0x67, 0x7e, 0x7c, 0xc6,
|
||||
0x82, 0xdb, 0x20, 0xc4, 0x89, 0x72, 0x96, 0xbf, 0xb3, 0x2a, 0xc6, 0x3b, 0x6b, 0x65, 0xaf, 0x71,
|
||||
0x06, 0x40, 0x4a, 0xd3, 0x8b, 0xef, 0x96, 0x66, 0x7e, 0xac, 0x0b, 0x54, 0x8e, 0x9d, 0x01, 0x74,
|
||||
0x2e, 0xa8, 0xe8, 0xe6, 0xbe, 0xb2, 0xb1, 0xa1, 0xc9, 0x95, 0xac, 0xcd, 0x72, 0xd1, 0x19, 0xc1,
|
||||
0xf6, 0x21, 0xf5, 0xae, 0x83, 0x68, 0xf2, 0x2a, 0x48, 0xc5, 0xb5, 0x45, 0xcf, 0xe8, 0x81, 0xe5,
|
||||
0x6b, 0x40, 0x4f, 0x29, 0x64, 0xe7, 0x23, 0x78, 0x68, 0xbc, 0x26, 0xcf, 0x39, 0xcd, 0xe3, 0xb1,
|
||||
0x0d, 0xf5, 0x54, 0x48, 0x72, 0x46, 0xdd, 0x55, 0x82, 0xf3, 0x25, 0x6c, 0x9b, 0xed, 0x55, 0x5c,
|
||||
0x2e, 0xf2, 0x83, 0xcb, 0xb6, 0x5f, 0x31, 0xda, 0xbe, 0x8e, 0x59, 0x75, 0xde, 0x2d, 0x36, 0xa1,
|
||||
0xf6, 0xeb, 0xaf, 0x2f, 0x74, 0xb2, 0x8b, 0xa1, 0xf3, 0x47, 0xe1, 0xbe, 0xbc, 0x9e, 0x72, 0x5f,
|
||||
0xea, 0xfd, 0x95, 0x77, 0xe9, 0xfd, 0x2b, 0xf2, 0xed, 0x23, 0xd8, 0x3a, 0x0d, 0x63, 0xef, 0xe6,
|
||||
0x28, 0x32, 0xa2, 0x61, 0x43, 0x13, 0x23, 0x33, 0x18, 0xb9, 0xe8, 0x7c, 0x00, 0x1b, 0x27, 0xe2,
|
||||
0x2d, 0x7f, 0x2a, 0x1e, 0x11, 0x45, 0x14, 0xe4, 0xf3, 0x5e, 0x9b, 0x2a, 0x61, 0xf4, 0xaf, 0x2a,
|
||||
0x34, 0x7f, 0xa5, 0x7e, 0x88, 0x90, 0x4f, 0xa1, 0x5b, 0xea, 0x38, 0xe4, 0xa1, 0x7c, 0xda, 0x2c,
|
||||
0xf6, 0xb7, 0xde, 0xa3, 0x25, 0x58, 0x79, 0x78, 0x0e, 0x1d, 0xb3, 0x9f, 0x10, 0xd9, 0x3b, 0xe4,
|
||||
0x7f, 0x93, 0x9e, 0x5c, 0x69, 0xb9, 0xd9, 0x9c, 0xc3, 0xf6, 0x2a, 0xa6, 0x27, 0x4f, 0xe6, 0x1e,
|
||||
0x96, 0xbb, 0x4c, 0xef, 0xbd, 0xfb, 0xb4, 0x79, 0x87, 0x68, 0x1e, 0x86, 0x48, 0xa3, 0x2c, 0x31,
|
||||
0x77, 0x30, 0x1f, 0x92, 0x17, 0xd0, 0x2d, 0xb1, 0xa1, 0x3a, 0xe7, 0x12, 0x41, 0x9a, 0x53, 0xf6,
|
||||
0xa0, 0x2e, 0x19, 0x98, 0x74, 0x4b, 0x44, 0xdf, 0x5b, 0x2f, 0x44, 0xe5, 0xbb, 0x0f, 0x6b, 0xf2,
|
||||
0x55, 0x67, 0x38, 0x96, 0x33, 0x0a, 0x7a, 0x1e, 0xfd, 0xa3, 0x02, 0xcd, 0xfc, 0x0f, 0xcb, 0x0b,
|
||||
0x58, 0x13, 0x44, 0x47, 0x1e, 0x18, 0x5c, 0x91, 0x93, 0x64, 0x6f, 0x7b, 0x01, 0x54, 0x0e, 0x86,
|
||||
0x50, 0x7b, 0x8d, 0x9c, 0x10, 0x43, 0xa9, 0x19, 0xaf, 0xf7, 0xa0, 0x8c, 0x15, 0xf6, 0x67, 0x59,
|
||||
0xd9, 0x5e, 0x13, 0x56, 0xc9, 0xbe, 0xa0, 0xa2, 0x9f, 0x41, 0x43, 0x51, 0x89, 0x0a, 0xca, 0x12,
|
||||
0x09, 0xa9, 0x8f, 0xbf, 0x4c, 0x3a, 0xa3, 0x7f, 0xd6, 0x00, 0xce, 0x67, 0x29, 0xc7, 0xe9, 0x6f,
|
||||
0x03, 0xbc, 0x23, 0xcf, 0x60, 0xe3, 0x15, 0x5e, 0xd1, 0x2c, 0xe4, 0xf2, 0xc2, 0x2f, 0x4a, 0xc6,
|
||||
0x88, 0x89, 0xbc, 0xb3, 0x14, 0x8c, 0xb4, 0x07, 0xed, 0x53, 0xfa, 0xe6, 0xed, 0x76, 0x9f, 0x42,
|
||||
0xb7, 0x44, 0x34, 0x7a, 0x8b, 0x8b, 0xd4, 0xa5, 0xb7, 0xb8, 0x4c, 0x49, 0x7b, 0xd0, 0xd4, 0xf4,
|
||||
0x63, 0xfa, 0x90, 0x44, 0x5d, 0xa2, 0xa5, 0x9f, 0xc2, 0xc6, 0x02, 0xf9, 0x98, 0xf6, 0xf2, 0x2f,
|
||||
0xd0, 0x4a, 0x72, 0x7a, 0x29, 0x2e, 0xec, 0x65, 0x02, 0x32, 0x27, 0xee, 0xa8, 0xa2, 0x5f, 0xc5,
|
||||
0x50, 0xaf, 0xcb, 0x57, 0x7d, 0xf9, 0xd0, 0xb1, 0x17, 0x39, 0x22, 0x67, 0xa8, 0x7c, 0xa1, 0x55,
|
||||
0x5c, 0xf3, 0x1c, 0x3a, 0x26, 0x4d, 0x2c, 0x95, 0xe0, 0x32, 0x87, 0xfc, 0x10, 0x60, 0xce, 0x14,
|
||||
0xa6, 0xbd, 0x4c, 0x8f, 0x05, 0x12, 0xb9, 0x6c, 0xc8, 0xc7, 0xc1, 0x8f, 0xfe, 0x13, 0x00, 0x00,
|
||||
0xff, 0xff, 0x54, 0xbe, 0x6c, 0x5a, 0x57, 0x15, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -435,6 +435,10 @@ message MlockEnabledReply {
|
|||
bool enabled = 1;
|
||||
}
|
||||
|
||||
message LocalMountReply {
|
||||
bool local = 1;
|
||||
}
|
||||
|
||||
service SystemView {
|
||||
rpc DefaultLeaseTTL(Empty) returns (TTLReply);
|
||||
rpc MaxLeaseTTL(Empty) returns (TTLReply);
|
||||
|
@ -444,6 +448,5 @@ service SystemView {
|
|||
rpc ReplicationState(Empty) returns (ReplicationStateReply);
|
||||
rpc ResponseWrapData(ResponseWrapDataArgs) returns (ResponseWrapDataReply);
|
||||
rpc MlockEnabled(Empty) returns (MlockEnabledReply);
|
||||
rpc LocalMount(Empty) returns (LocalMountReply);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ func TestTranslation_Errors(t *testing.T) {
|
|||
e := ProtoErrToErr(pe)
|
||||
|
||||
if !reflect.DeepEqual(e, err) {
|
||||
t.Fatal("Errs did not match: %#v, %#v", e, err)
|
||||
t.Fatalf("Errs did not match: %#v, %#v", e, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func TestTranslation_StorageEntry(t *testing.T) {
|
|||
e := ProtoStorageEntryToLogicalStorageEntry(p)
|
||||
|
||||
if !reflect.DeepEqual(c, e) {
|
||||
t.Fatal("Entries did not match: %#v, %#v", e, c)
|
||||
t.Fatalf("Entries did not match: %#v, %#v", e, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,6 +119,16 @@ func (s *SystemViewClient) MlockEnabled() bool {
|
|||
return reply.MlockEnabled
|
||||
}
|
||||
|
||||
func (s *SystemViewClient) LocalMount() bool {
|
||||
var reply LocalMountReply
|
||||
err := s.client.Call("Plugin.LocalMount", new(interface{}), &reply)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return reply.Local
|
||||
}
|
||||
|
||||
type SystemViewServer struct {
|
||||
impl logical.SystemView
|
||||
}
|
||||
|
@ -202,6 +212,15 @@ func (s *SystemViewServer) MlockEnabled(_ interface{}, reply *MlockEnabledReply)
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *SystemViewServer) LocalMount(_ interface{}, reply *LocalMountReply) error {
|
||||
local := s.impl.LocalMount()
|
||||
*reply = LocalMountReply{
|
||||
Local: local,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DefaultLeaseTTLReply struct {
|
||||
DefaultLeaseTTL time.Duration
|
||||
}
|
||||
|
@ -245,3 +264,7 @@ type ResponseWrapDataReply struct {
|
|||
type MlockEnabledReply struct {
|
||||
MlockEnabled bool
|
||||
}
|
||||
|
||||
type LocalMountReply struct {
|
||||
Local bool
|
||||
}
|
||||
|
|
|
@ -39,6 +39,10 @@ type SystemView interface {
|
|||
// despite known slowdowns.
|
||||
CachingDisabled() bool
|
||||
|
||||
// When run from a system view attached to a request, indicates whether the
|
||||
// request is affecting a local mount or not
|
||||
LocalMount() bool
|
||||
|
||||
// ReplicationState indicates the state of cluster replication
|
||||
ReplicationState() consts.ReplicationState
|
||||
|
||||
|
@ -63,6 +67,7 @@ type StaticSystemView struct {
|
|||
CachingDisabledVal bool
|
||||
Primary bool
|
||||
EnableMlock bool
|
||||
LocalMountVal bool
|
||||
ReplicationStateVal consts.ReplicationState
|
||||
}
|
||||
|
||||
|
@ -86,6 +91,10 @@ func (d StaticSystemView) CachingDisabled() bool {
|
|||
return d.CachingDisabledVal
|
||||
}
|
||||
|
||||
func (d StaticSystemView) LocalMount() bool {
|
||||
return d.LocalMountVal
|
||||
}
|
||||
|
||||
func (d StaticSystemView) ReplicationState() consts.ReplicationState {
|
||||
return d.ReplicationStateVal
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
type InmemHABackend struct {
|
||||
physical.Backend
|
||||
locks map[string]string
|
||||
l sync.Mutex
|
||||
l *sync.Mutex
|
||||
cond *sync.Cond
|
||||
logger log.Logger
|
||||
}
|
||||
|
@ -32,8 +32,9 @@ func NewInmemHA(_ map[string]string, logger log.Logger) (physical.Backend, error
|
|||
Backend: be,
|
||||
locks: make(map[string]string),
|
||||
logger: logger,
|
||||
l: new(sync.Mutex),
|
||||
}
|
||||
in.cond = sync.NewCond(&in.l)
|
||||
in.cond = sync.NewCond(in.l)
|
||||
return in, nil
|
||||
}
|
||||
|
||||
|
@ -46,13 +47,14 @@ func NewTransactionalInmemHA(_ map[string]string, logger log.Logger) (physical.B
|
|||
Backend: transInmem,
|
||||
locks: make(map[string]string),
|
||||
logger: logger,
|
||||
l: new(sync.Mutex),
|
||||
}
|
||||
|
||||
in := &TransactionalInmemHABackend{
|
||||
InmemHABackend: inmemHA,
|
||||
Transactional: transInmem.(physical.Transactional),
|
||||
}
|
||||
in.cond = sync.NewCond(&in.l)
|
||||
in.cond = sync.NewCond(in.l)
|
||||
return in, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,13 @@ func NewZooKeeperBackend(conf map[string]string, logger log.Logger) (physical.Ba
|
|||
}
|
||||
}
|
||||
|
||||
acl := []zk.ACL{{zk.PermAll, schema, owner}}
|
||||
acl := []zk.ACL{
|
||||
{
|
||||
Perms: zk.PermAll,
|
||||
Scheme: schema,
|
||||
ID: owner,
|
||||
},
|
||||
}
|
||||
|
||||
// Authnetication info
|
||||
var schemaAndUser string
|
||||
|
|
|
@ -364,10 +364,7 @@ func (c *Core) ClusterTLSConfig(ctx context.Context) (*tls.Config, error) {
|
|||
PrivateKey: localSigner,
|
||||
Leaf: parsedCert,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
clientLookup := func(requestInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
||||
|
|
|
@ -338,7 +338,6 @@ func testCluster_ForwardRequests(t *testing.T, c *TestClusterCore, rootToken, re
|
|||
// We need to call Leader as that refreshes the connection info
|
||||
isLeader, _, _, err := c.Leader()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
t.Fatal(err)
|
||||
}
|
||||
if isLeader {
|
||||
|
|
|
@ -85,6 +85,10 @@ func (d dynamicSystemView) CachingDisabled() bool {
|
|||
return d.core.cachingDisabled || (d.mountEntry != nil && d.mountEntry.Config.ForceNoCache)
|
||||
}
|
||||
|
||||
func (d dynamicSystemView) LocalMount() bool {
|
||||
return d.mountEntry != nil && d.mountEntry.Local
|
||||
}
|
||||
|
||||
// Checks if this is a primary Vault instance. Caller should hold the stateLock
|
||||
// in read mode.
|
||||
func (d dynamicSystemView) ReplicationState() consts.ReplicationState {
|
||||
|
|
|
@ -1322,6 +1322,11 @@ func (i *IdentityStore) sanitizeAndUpsertGroup(group *identity.Group, memberGrou
|
|||
}
|
||||
|
||||
func (i *IdentityStore) validateMemberGroupID(groupID string, memberGroupID string) error {
|
||||
// Detect self loop
|
||||
if groupID == memberGroupID {
|
||||
return fmt.Errorf("member group ID %q is same as the ID of the group", groupID)
|
||||
}
|
||||
|
||||
group, err := i.MemDBGroupByID(groupID, true)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1333,11 +1338,6 @@ func (i *IdentityStore) validateMemberGroupID(groupID string, memberGroupID stri
|
|||
return nil
|
||||
}
|
||||
|
||||
// Detect self loop
|
||||
if groupID == memberGroupID {
|
||||
fmt.Errorf("member group ID %q is same as the ID of the group")
|
||||
}
|
||||
|
||||
// If adding the memberGroupID to groupID creates a cycle, then groupID must
|
||||
// be a hop in that loop. Start a DFS traversal from memberGroupID and see if
|
||||
// it reaches back to groupID. If it does, then it's a loop.
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
math "math"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -263,7 +264,11 @@ func (c *Core) refreshRequestForwardingConnection(ctx context.Context, clusterAd
|
|||
grpc.WithInsecure(), // it's not, we handle it in the dialer
|
||||
grpc.WithKeepaliveParams(keepalive.ClientParameters{
|
||||
Time: 2 * HeartbeatInterval,
|
||||
}))
|
||||
}),
|
||||
grpc.WithDefaultCallOptions(
|
||||
grpc.MaxCallRecvMsgSize(math.MaxInt32),
|
||||
grpc.MaxCallSendMsgSize(math.MaxInt32),
|
||||
))
|
||||
if err != nil {
|
||||
cancelFunc()
|
||||
c.logger.Error("core: err setting up forwarding rpc client", "error", err)
|
||||
|
|
|
@ -175,6 +175,10 @@ func (m *RollbackManager) attemptRollback(ctx context.Context, path string, rs *
|
|||
if err == logical.ErrUnsupportedOperation {
|
||||
err = nil
|
||||
}
|
||||
// If we failed due to read-only storage, we can't do anything; ignore
|
||||
if err != nil && strings.Contains(err.Error(), logical.ErrReadOnly.Error()) {
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
m.logger.Error("rollback: error rolling back", "path", path, "error", err)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package plugin
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
"net/rpc"
|
||||
|
||||
|
@ -10,6 +11,18 @@ import (
|
|||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// TestOptions allows specifying options that can affect the behavior of the
|
||||
// test functions
|
||||
type TestOptions struct {
|
||||
//ServerStdout causes the given value to be used in place of a blank buffer
|
||||
//for RPCServer's Stdout
|
||||
ServerStdout io.ReadCloser
|
||||
|
||||
//ServerStderr causes the given value to be used in place of a blank buffer
|
||||
//for RPCServer's Stderr
|
||||
ServerStderr io.ReadCloser
|
||||
}
|
||||
|
||||
// The testing file contains test helpers that you can use outside of
|
||||
// this package for making it easier to test plugins themselves.
|
||||
|
||||
|
@ -61,12 +74,20 @@ func TestRPCConn(t testing.T) (*rpc.Client, *rpc.Server) {
|
|||
|
||||
// TestPluginRPCConn returns a plugin RPC client and server that are connected
|
||||
// together and configured.
|
||||
func TestPluginRPCConn(t testing.T, ps map[string]Plugin) (*RPCClient, *RPCServer) {
|
||||
func TestPluginRPCConn(t testing.T, ps map[string]Plugin, opts *TestOptions) (*RPCClient, *RPCServer) {
|
||||
// Create two net.Conns we can use to shuttle our control connection
|
||||
clientConn, serverConn := TestConn(t)
|
||||
|
||||
// Start up the server
|
||||
server := &RPCServer{Plugins: ps, Stdout: new(bytes.Buffer), Stderr: new(bytes.Buffer)}
|
||||
if opts != nil {
|
||||
if opts.ServerStdout != nil {
|
||||
server.Stdout = opts.ServerStdout
|
||||
}
|
||||
if opts.ServerStderr != nil {
|
||||
server.Stderr = opts.ServerStderr
|
||||
}
|
||||
}
|
||||
go server.ServeConn(serverConn)
|
||||
|
||||
// Connect the client to the server
|
||||
|
|
|
@ -101,6 +101,9 @@ type Conn struct {
|
|||
reconnectLatch chan struct{}
|
||||
setWatchLimit int
|
||||
setWatchCallback func([]*setWatchesRequest)
|
||||
// Debug (for recurring re-auth hang)
|
||||
debugCloseRecvLoop bool
|
||||
debugReauthDone chan struct{}
|
||||
|
||||
logger Logger
|
||||
logInfo bool // true if information messages are logged; false if only errors are logged
|
||||
|
@ -301,9 +304,9 @@ func WithMaxBufferSize(maxBufferSize int) connOption {
|
|||
// to a limit of 1mb. This option should be used for non-standard server setup
|
||||
// where znode is bigger than default 1mb.
|
||||
func WithMaxConnBufferSize(maxBufferSize int) connOption {
|
||||
return func(c *Conn) {
|
||||
c.buf = make([]byte, maxBufferSize)
|
||||
}
|
||||
return func(c *Conn) {
|
||||
c.buf = make([]byte, maxBufferSize)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Conn) Close() {
|
||||
|
@ -389,6 +392,17 @@ func (c *Conn) connect() error {
|
|||
}
|
||||
|
||||
func (c *Conn) resendZkAuth(reauthReadyChan chan struct{}) {
|
||||
shouldCancel := func() bool {
|
||||
select {
|
||||
case <-c.shouldQuit:
|
||||
return true
|
||||
case <-c.closeChan:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
c.credsMu.Lock()
|
||||
defer c.credsMu.Unlock()
|
||||
|
||||
|
@ -400,6 +414,10 @@ func (c *Conn) resendZkAuth(reauthReadyChan chan struct{}) {
|
|||
}
|
||||
|
||||
for _, cred := range c.creds {
|
||||
if shouldCancel() {
|
||||
c.logger.Printf("Cancel rer-submitting credentials")
|
||||
return
|
||||
}
|
||||
resChan, err := c.sendRequest(
|
||||
opSetAuth,
|
||||
&setAuthRequest{Type: 0,
|
||||
|
@ -415,7 +433,16 @@ func (c *Conn) resendZkAuth(reauthReadyChan chan struct{}) {
|
|||
continue
|
||||
}
|
||||
|
||||
res := <-resChan
|
||||
var res response
|
||||
select {
|
||||
case res = <-resChan:
|
||||
case <-c.closeChan:
|
||||
c.logger.Printf("Recv closed, cancel re-submitting credentials")
|
||||
return
|
||||
case <-c.shouldQuit:
|
||||
c.logger.Printf("Should quit, cancel re-submitting credentials")
|
||||
return
|
||||
}
|
||||
if res.err != nil {
|
||||
c.logger.Printf("Credential re-submit failed: %s", res.err)
|
||||
// FIXME(prozlach): lets ignore errors for now
|
||||
|
@ -476,6 +503,9 @@ func (c *Conn) loop() {
|
|||
wg.Add(1)
|
||||
go func() {
|
||||
<-reauthChan
|
||||
if c.debugCloseRecvLoop {
|
||||
close(c.debugReauthDone)
|
||||
}
|
||||
err := c.sendLoop()
|
||||
if err != nil || c.logInfo {
|
||||
c.logger.Printf("Send loop terminated: err=%v", err)
|
||||
|
@ -486,7 +516,12 @@ func (c *Conn) loop() {
|
|||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
err := c.recvLoop(c.conn)
|
||||
var err error
|
||||
if c.debugCloseRecvLoop {
|
||||
err = errors.New("DEBUG: close recv loop")
|
||||
} else {
|
||||
err = c.recvLoop(c.conn)
|
||||
}
|
||||
if err != io.EOF || c.logInfo {
|
||||
c.logger.Printf("Recv loop terminated: err=%v", err)
|
||||
}
|
||||
|
|
|
@ -1003,10 +1003,10 @@
|
|||
"revisionTime": "2017-12-04T18:29:08Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "y3op+t01flBlSBKlzUNqH5d4XHQ=",
|
||||
"checksumSHA1": "7SheX5w6+xGsTMxPI3LiJx0iz7s=",
|
||||
"path": "github.com/hashicorp/go-plugin",
|
||||
"revision": "e53f54cbf51efde642d4711313e829a1ff0c236d",
|
||||
"revisionTime": "2018-01-25T19:04:38Z"
|
||||
"revision": "4b17561773d85e482ea040884ee3e288425d4174",
|
||||
"revisionTime": "2018-02-06T18:30:35Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "yzoWV7yrS/TvOrKy5ZrdUjsYaOA=",
|
||||
|
@ -1495,10 +1495,10 @@
|
|||
"revisionTime": "2017-01-28T01:21:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "y33yd1uDZmV3VY4K/5FCGTeRtB8=",
|
||||
"checksumSHA1": "ze1R6Lrk0kW0cX24ZdZD6ZpIDCo=",
|
||||
"path": "github.com/samuel/go-zookeeper/zk",
|
||||
"revision": "471cd4e61d7a78ece1791fa5faa0345dc8c7d5a5",
|
||||
"revisionTime": "2017-11-17T18:40:27Z"
|
||||
"revision": "c4fab1ac1bec58281ad0667dc3f0907a9476ac47",
|
||||
"revisionTime": "2018-01-30T19:37:22Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "eDQ6f1EsNf+frcRO/9XukSEchm8=",
|
||||
|
|
|
@ -10,8 +10,9 @@ description: |-
|
|||
# Multi-Factor Authentication
|
||||
|
||||
~> **NOTE**: This page describes the legacy MFA system available in the OSS
|
||||
edition of Vault. Vault Enterprise contains a significantly more complete and
|
||||
flexible MFA system that can be used throughout Vault's API. See the [Vault
|
||||
edition of Vault. This system is not supported by HashiCorp. Vault Enterprise
|
||||
contains a fully-supported MFA system that is significantly more complete and
|
||||
flexible and which can be used throughout Vault's API. See the [Vault
|
||||
Enterprise MFA](/docs/enterprise/mfa/index.html) page for more information.
|
||||
|
||||
Several auth methods support multi-factor authentication (MFA). Once
|
||||
|
|
|
@ -117,7 +117,7 @@ This example show enabling high availability for the Etcd storage backend.
|
|||
api_addr = "https://vault-leader.my-company.internal"
|
||||
|
||||
storage "etcd" {
|
||||
ha_enabled = true
|
||||
ha_enabled = "true"
|
||||
...
|
||||
}
|
||||
```
|
||||
|
|
|
@ -478,10 +478,6 @@
|
|||
<a href="/docs/auth/ldap.html">LDAP</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-auth-mfa") %>>
|
||||
<a href="/docs/auth/mfa.html">MFA</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-auth-okta") %>>
|
||||
<a href="/docs/auth/okta.html">Okta</a>
|
||||
</li>
|
||||
|
@ -508,6 +504,10 @@
|
|||
<a href="/docs/auth/app-id.html">App ID <sup>DEPRECATED</sup></a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-auth-mfa") %>>
|
||||
<a href="/docs/auth/mfa.html">MFA <sup>LEGACY / UNSUPPORTED</sup></a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
|
Loading…
Reference in New Issue