func getDuoAuthClient(data *MockClientData) AuthClient { var c MockAuthClient // set default response to be successful preauthSuccessJSON := ` { "Stat": "OK", "Response": { "Result": "auth", "Status_Msg": "Needs authentication", "Devices": [] } }` if data.PreauthData == nil { data.PreauthData = &authapi.PreauthResult{} jsonutil.DecodeJSON([]byte(preauthSuccessJSON), data.PreauthData) } authSuccessJSON := ` { "Stat": "OK", "Response": { "Result": "allow" } }` if data.AuthData == nil { data.AuthData = &authapi.AuthResult{} jsonutil.DecodeJSON([]byte(authSuccessJSON), data.AuthData) } c.MockData = data return &c }
func TestFormatJSON_formatRequest(t *testing.T) { cases := map[string]struct { Auth *logical.Auth Req *logical.Request Err error Result string }{ "auth, request": { &logical.Auth{ClientToken: "foo", Policies: []string{"root"}}, &logical.Request{ Operation: logical.UpdateOperation, Path: "/foo", Connection: &logical.Connection{ RemoteAddr: "127.0.0.1", }, WrapTTL: 60 * time.Second, }, errors.New("this is an error"), testFormatJSONReqBasicStr, }, } for name, tc := range cases { var buf bytes.Buffer formatter := AuditFormatter{ AuditFormatWriter: &JSONFormatWriter{}, } salter, _ := salt.NewSalt(nil, nil) config := FormatterConfig{ Salt: salter, } if err := formatter.FormatRequest(&buf, config, tc.Auth, tc.Req, tc.Err); err != nil { t.Fatalf("bad: %s\nerr: %s", name, err) } var expectedjson = new(AuditRequestEntry) if err := jsonutil.DecodeJSON([]byte(tc.Result), &expectedjson); err != nil { t.Fatalf("bad json: %s", err) } var actualjson = new(AuditRequestEntry) if err := jsonutil.DecodeJSON([]byte(buf.String()), &actualjson); err != nil { t.Fatalf("bad json: %s", err) } expectedjson.Time = actualjson.Time expectedBytes, err := json.Marshal(expectedjson) if err != nil { t.Fatalf("unable to marshal json: %s", err) } if strings.TrimSpace(buf.String()) != string(expectedBytes) { t.Fatalf( "bad: %s\nResult:\n\n'%s'\n\nExpected:\n\n'%s'", name, buf.String(), string(expectedBytes)) } } }
// DeserializeKey is used to deserialize and return a new key func DeserializeKey(buf []byte) (*Key, error) { k := new(Key) if err := jsonutil.DecodeJSON(buf, k); err != nil { return nil, fmt.Errorf("deserialization failed: %v", err) } return k, nil }
func (b *CubbyholeBackend) handleRead( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { if req.ClientToken == "" { return nil, fmt.Errorf("cubbyhole read: client token empty") } // Read the path out, err := req.Storage.Get(req.ClientToken + "/" + req.Path) if err != nil { return nil, fmt.Errorf("read failed: %v", err) } // Fast-path the no data case if out == nil { return nil, nil } // Decode the data var rawData map[string]interface{} if err := jsonutil.DecodeJSON(out.Value, &rawData); err != nil { return nil, fmt.Errorf("json decoding failed: %v", err) } // Generate the response resp := &logical.Response{ Data: rawData, } return resp, nil }
func TestDuoHandlerReject(t *testing.T) { AuthData := &authapi.AuthResult{} authRejectJSON := ` { "Stat": "OK", "Response": { "Result": "deny", "Status_Msg": "Invalid auth" } }` jsonutil.DecodeJSON([]byte(authRejectJSON), AuthData) successResp := &logical.Response{ Auth: &logical.Auth{}, } expectedError := AuthData.Response.Status_Msg duoConfig := &DuoConfig{ UsernameFormat: "%s", } duoAuthClient := getDuoAuthClient(&MockClientData{ AuthData: AuthData, }) resp, err := duoHandler(duoConfig, duoAuthClient, &duoAuthRequest{ successResp: successResp, username: "******", }) if err != nil { t.Fatalf(err.Error()) } error, ok := resp.Data["error"].(string) if !ok || !strings.Contains(error, expectedError) { t.Fatalf("Testing Duo authentication gave incorrect response (expected deny, got: %v)", error) } }
// Registers a new role with the backend func (b *backend) pathRoleUpdate(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { name := d.Get("name").(string) if name == "" { return logical.ErrorResponse("missing name"), nil } tags := d.Get("tags").(string) rawVHosts := d.Get("vhosts").(string) if tags == "" && rawVHosts == "" { return logical.ErrorResponse("both tags and vhosts not specified"), nil } var vhosts map[string]vhostPermission if len(rawVHosts) > 0 { if err := jsonutil.DecodeJSON([]byte(rawVHosts), &vhosts); err != nil { return logical.ErrorResponse(fmt.Sprintf("failed to unmarshal vhosts: %s", err)), nil } } // Store it entry, err := logical.StorageEntryJSON("role/"+name, &roleEntry{ Tags: tags, VHosts: vhosts, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
// loadCredentials is invoked as part of postUnseal to load the auth table func (c *Core) loadCredentials() error { authTable := &MountTable{} // Load the existing mount table raw, err := c.barrier.Get(coreAuthConfigPath) if err != nil { c.logger.Printf("[ERR] core: failed to read auth table: %v", err) return errLoadAuthFailed } c.authLock.Lock() defer c.authLock.Unlock() if raw != nil { if err := jsonutil.DecodeJSON(raw.Value, authTable); err != nil { c.logger.Printf("[ERR] core: failed to decode auth table: %v", err) return errLoadAuthFailed } c.auth = authTable } // Done if we have restored the auth table if c.auth != nil { needPersist := false // Upgrade to typed auth table if c.auth.Type == "" { c.auth.Type = credentialTableType needPersist = true } // Upgrade to table-scoped entries for _, entry := range c.auth.Entries { // The auth backend "aws-ec2" was named "aws" in the master. // This is to support upgrade procedure from "aws" to "aws-ec2". if entry.Type == "aws" { entry.Type = "aws-ec2" needPersist = true } if entry.Table == "" { entry.Table = c.auth.Type needPersist = true } } if needPersist { return c.persistAuth(c.auth) } return nil } // Create and persist the default auth table c.auth = defaultAuthTable() if err := c.persistAuth(c.auth); err != nil { c.logger.Printf("[ERR] core: failed to persist auth table: %v", err) return errLoadAuthFailed } return nil }
// RekeyRetrieveBackup is used to retrieve any backed-up PGP-encrypted unseal // keys func (c *Core) RekeyRetrieveBackup(recovery bool) (*RekeyBackup, error) { c.stateLock.RLock() defer c.stateLock.RUnlock() if c.sealed { return nil, ErrSealed } if c.standby { return nil, ErrStandby } c.rekeyLock.RLock() defer c.rekeyLock.RUnlock() var entry *physical.Entry var err error if recovery { entry, err = c.physical.Get(coreRecoveryUnsealKeysBackupPath) } else { entry, err = c.physical.Get(coreBarrierUnsealKeysBackupPath) } if err != nil { return nil, err } if entry == nil { return nil, nil } ret := &RekeyBackup{} err = jsonutil.DecodeJSON(entry.Value, ret) if err != nil { return nil, err } return ret, nil }
// ParseForwardedRequest generates a new http.Request that is comprised of the // values in the given request's body, assuming it correctly parses into a // ForwardedRequest. func ParseForwardedRequest(req *http.Request) (*http.Request, error) { buf := bufCloser{ Buffer: bytes.NewBuffer(nil), } _, err := buf.ReadFrom(req.Body) if err != nil { return nil, err } var fq ForwardedRequest err = jsonutil.DecodeJSON(buf.Bytes(), &fq) if err != nil { return nil, err } buf.Reset() _, err = buf.Write(fq.Body) if err != nil { return nil, err } ret := &http.Request{ Method: fq.Method, URL: fq.URL, Header: fq.Header, Body: buf, Host: fq.Host, RemoteAddr: fq.RemoteAddr, TLS: fq.ConnectionState, } return ret, nil }
// ParsePKIJSON takes a JSON-encoded string and returns a ParsedCertBundle. // // This can be either the output of an // issue call from the PKI backend or just its data member; or, // JSON not coming from the PKI backend. func ParsePKIJSON(input []byte) (*ParsedCertBundle, error) { result := &CertBundle{} err := jsonutil.DecodeJSON(input, &result) if err == nil { return result.ToParsedCertBundle() } var secret Secret err = jsonutil.DecodeJSON(input, &secret) if err == nil { return ParsePKIMap(secret.Data) } return nil, errutil.UserError{"unable to parse out of either secret data or a secret object"} }
func (b *PassthroughBackend) handleRead( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { // Read the path out, err := req.Storage.Get(req.Path) if err != nil { return nil, fmt.Errorf("read failed: %v", err) } // Fast-path the no data case if out == nil { return nil, nil } // Decode the data var rawData map[string]interface{} if err := jsonutil.DecodeJSON(out.Value, &rawData); err != nil { return nil, fmt.Errorf("json decoding failed: %v", err) } var resp *logical.Response if b.generateLeases { // Generate the response resp = b.Secret("generic").Response(rawData, nil) resp.Secret.Renewable = false } else { resp = &logical.Response{ Secret: &logical.Secret{}, Data: rawData, } } // Check if there is a ttl key var ttl string ttl, _ = rawData["ttl"].(string) if len(ttl) == 0 { ttl, _ = rawData["lease"].(string) } ttlDuration := b.System().DefaultLeaseTTL() if len(ttl) != 0 { dur, err := duration.ParseDurationSecond(ttl) if err == nil { ttlDuration = dur } if b.generateLeases { resp.Secret.Renewable = true } } resp.Secret.TTL = ttlDuration return resp, nil }
// loadAudits is invoked as part of postUnseal to load the audit table func (c *Core) loadAudits() error { auditTable := &MountTable{} // Load the existing audit table raw, err := c.barrier.Get(coreAuditConfigPath) if err != nil { c.logger.Error("core: failed to read audit table", "error", err) return errLoadAuditFailed } c.auditLock.Lock() defer c.auditLock.Unlock() if raw != nil { if err := jsonutil.DecodeJSON(raw.Value, auditTable); err != nil { c.logger.Error("core: failed to decode audit table", "error", err) return errLoadAuditFailed } c.audit = auditTable } // Done if we have restored the audit table if c.audit != nil { needPersist := false // Upgrade to typed auth table if c.audit.Type == "" { c.audit.Type = auditTableType needPersist = true } // Upgrade to table-scoped entries for _, entry := range c.audit.Entries { if entry.Table == "" { entry.Table = c.audit.Type needPersist = true } } if needPersist { return c.persistAudit(c.audit) } return nil } // Create and persist the default audit table c.audit = defaultAuditTable() if err := c.persistAudit(c.audit); err != nil { return errLoadAuditFailed } return nil }
func testAccStepReadRole(t *testing.T, name, tags, rawVHosts string) logicaltest.TestStep { return logicaltest.TestStep{ Operation: logical.ReadOperation, Path: "roles/" + name, Check: func(resp *logical.Response) error { if resp == nil { if tags == "" && rawVHosts == "" { return nil } return fmt.Errorf("bad: %#v", resp) } var d struct { Tags string `mapstructure:"tags"` VHosts map[string]vhostPermission `mapstructure:"vhosts"` } if err := mapstructure.Decode(resp.Data, &d); err != nil { return err } if d.Tags != tags { return fmt.Errorf("bad: %#v", resp) } var vhosts map[string]vhostPermission if err := jsonutil.DecodeJSON([]byte(rawVHosts), &vhosts); err != nil { return fmt.Errorf("bad expected vhosts %#v: %s", vhosts, err) } for host, permission := range vhosts { actualPermission, ok := d.VHosts[host] if !ok { return fmt.Errorf("expected vhost: %s", host) } if actualPermission.Configure != permission.Configure { return fmt.Errorf("expected permission %s to be %s, got %s", "configure", permission.Configure, actualPermission.Configure) } if actualPermission.Write != permission.Write { return fmt.Errorf("expected permission %s to be %s, got %s", "write", permission.Write, actualPermission.Write) } if actualPermission.Read != permission.Read { return fmt.Errorf("expected permission %s to be %s, got %s", "read", permission.Read, actualPermission.Read) } } return nil }, } }
// Verifies the correctness of the authenticated attributes present in the PKCS#7 // signature. After verification, extracts the instance identity document from the // signature, parses it and returns it. func (b *backend) parseIdentityDocument(s logical.Storage, pkcs7B64 string) (*identityDocument, error) { // Insert the header and footer for the signature to be able to pem decode it pkcs7B64 = fmt.Sprintf("-----BEGIN PKCS7-----\n%s\n-----END PKCS7-----", pkcs7B64) // Decode the PEM encoded signature pkcs7BER, pkcs7Rest := pem.Decode([]byte(pkcs7B64)) if len(pkcs7Rest) != 0 { return nil, fmt.Errorf("failed to decode the PEM encoded PKCS#7 signature") } // Parse the signature from asn1 format into a struct pkcs7Data, err := pkcs7.Parse(pkcs7BER.Bytes) if err != nil { return nil, fmt.Errorf("failed to parse the BER encoded PKCS#7 signature: %v\n", err) } // Get the public certificates that are used to verify the signature. // This returns a slice of certificates containing the default certificate // and all the registered certificates via 'config/certificate/<cert_name>' endpoint publicCerts, err := b.awsPublicCertificates(s, true) if err != nil { return nil, err } if publicCerts == nil || len(publicCerts) == 0 { return nil, fmt.Errorf("certificates to verify the signature are not found") } // Before calling Verify() on the PKCS#7 struct, set the certificates to be used // to verify the contents in the signer information. pkcs7Data.Certificates = publicCerts // Verify extracts the authenticated attributes in the PKCS#7 signature, and verifies // the authenticity of the content using 'dsa.PublicKey' embedded in the public certificate. if pkcs7Data.Verify() != nil { return nil, fmt.Errorf("failed to verify the signature") } // Check if the signature has content inside of it if len(pkcs7Data.Content) == 0 { return nil, fmt.Errorf("instance identity document could not be found in the signature") } var identityDoc identityDocument if err := jsonutil.DecodeJSON(pkcs7Data.Content, &identityDoc); err != nil { return nil, err } return &identityDoc, nil }
func (d *DefaultSeal) BarrierConfig() (*SealConfig, error) { if d.config != nil { return d.config.Clone(), nil } if err := d.checkCore(); err != nil { return nil, err } // Fetch the core configuration pe, err := d.core.physical.Get(barrierSealConfigPath) if err != nil { d.core.logger.Error("core: failed to read seal configuration", "error", err) return nil, fmt.Errorf("failed to check seal configuration: %v", err) } // If the seal configuration is missing, we are not initialized if pe == nil { d.core.logger.Info("core: seal configuration missing, not initialized") return nil, nil } var conf SealConfig // Decode the barrier entry if err := jsonutil.DecodeJSON(pe.Value, &conf); err != nil { d.core.logger.Error("core: failed to decode seal configuration", "error", err) return nil, fmt.Errorf("failed to decode seal configuration: %v", err) } switch conf.Type { // This case should not be valid for other types as only this is the default case "": conf.Type = d.BarrierType() case d.BarrierType(): default: d.core.logger.Error("core: barrier seal type does not match loaded type", "barrier_seal_type", conf.Type, "loaded_seal_type", d.BarrierType()) return nil, fmt.Errorf("barrier seal type of %s does not match loaded type of %s", conf.Type, d.BarrierType()) } // Check for a valid seal configuration if err := conf.Validate(); err != nil { d.core.logger.Error("core: invalid seal configuration", "error", err) return nil, fmt.Errorf("seal validation failed: %v", err) } d.config = &conf return d.config.Clone(), nil }
// MarshalJSON implements JSON unmarshaling func (kem keyEntryMap) UnmarshalJSON(data []byte) error { intermediate := map[string]keyEntry{} if err := jsonutil.DecodeJSON(data, &intermediate); err != nil { return err } for k, v := range intermediate { keyval, err := strconv.Atoi(k) if err != nil { return err } kem[keyval] = v } return nil }
func TestJsonFormatter(t *testing.T) { ui := mockUi{t: t, SampleData: "something"} if err := outputWithFormat(ui, "json", nil, ui); err != 0 { t.Fatal(err) } var newUi mockUi if err := jsonutil.DecodeJSON([]byte(output), &newUi); err != nil { t.Fatal(err) } if newUi.SampleData != ui.SampleData { t.Fatalf(`values not equal ("%s" != "%s")`, newUi.SampleData, ui.SampleData) } }
// Get reads the structure. func (p *PathStruct) Get(s logical.Storage) (map[string]interface{}, error) { entry, err := s.Get(fmt.Sprintf("struct/%s", p.Name)) if err != nil { return nil, err } if entry == nil { return nil, nil } var result map[string]interface{} if err := jsonutil.DecodeJSON(entry.Value, &result); err != nil { return nil, err } return result, nil }
// GetWAL reads a specific entry from the WAL. If the entry doesn't exist, // then nil value is returned. // // The kind, value, and error are returned. func GetWAL(s logical.Storage, id string) (*WALEntry, error) { entry, err := s.Get(WALPrefix + id) if err != nil { return nil, err } if entry == nil { return nil, nil } var raw WALEntry if err := jsonutil.DecodeJSON(entry.Value, &raw); err != nil { return nil, err } raw.ID = id return &raw, nil }
// DeserializeKeyring is used to deserialize and return a new keyring func DeserializeKeyring(buf []byte) (*Keyring, error) { // Deserialize the keyring var enc EncodedKeyring if err := jsonutil.DecodeJSON(buf, &enc); err != nil { return nil, fmt.Errorf("deserialization failed: %v", err) } // Create a new keyring k := NewKeyring() k.masterKey = enc.MasterKey for _, key := range enc.Keys { k.keys[key.Term] = key if key.Term > k.activeTerm { k.activeTerm = key.Term } } return k, nil }
func (p *policy) loadArchive(storage logical.Storage) (*archivedKeys, error) { archive := &archivedKeys{} raw, err := storage.Get("archive/" + p.Name) if err != nil { return nil, err } if raw == nil { archive.Keys = make([]keyEntry, 0) return archive, nil } if err := jsonutil.DecodeJSON(raw.Value, archive); err != nil { return nil, err } return archive, nil }
// ParseForwardedRequest generates a new http.Request that is comprised of the // values in the given request's body, assuming it correctly parses into a // ForwardedRequest. func ParseForwardedHTTPRequest(req *http.Request) (*http.Request, error) { buf := bytes.NewBuffer(nil) _, err := buf.ReadFrom(req.Body) if err != nil { return nil, err } fq := new(Request) switch os.Getenv("VAULT_MESSAGE_TYPE") { case "json", "json_compress": err = jsonutil.DecodeJSON(buf.Bytes(), fq) default: err = proto.Unmarshal(buf.Bytes(), fq) } if err != nil { return nil, err } return ParseForwardedRequest(fq) }
func (lm *lockManager) getStoredPolicy(storage logical.Storage, name string) (*policy, error) { // Check if the policy already exists raw, err := storage.Get("policy/" + name) if err != nil { return nil, err } if raw == nil { return nil, nil } // Decode the policy policy := &policy{ Keys: keyEntryMap{}, } err = jsonutil.DecodeJSON(raw.Value, policy) if err != nil { return nil, err } return policy, nil }
// Error returns an error response if there is one. If there is an error, // this will fully consume the response body, but will not close it. The // body must still be closed manually. func (r *Response) Error() error { // 200 to 399 are okay status codes if r.StatusCode >= 200 && r.StatusCode < 400 { return nil } // We have an error. Let's copy the body into our own buffer first, // so that if we can't decode JSON, we can at least copy it raw. var bodyBuf bytes.Buffer if _, err := io.Copy(&bodyBuf, r.Body); err != nil { return err } // Decode the error response if we can. Note that we wrap the bodyBuf // in a bytes.Reader here so that the JSON decoder doesn't move the // read pointer for the original buffer. var resp ErrorResponse if err := jsonutil.DecodeJSON(bodyBuf.Bytes(), &resp); err != nil { // Ignore the decoding error and just drop the raw response return fmt.Errorf( "Error making API request.\n\n"+ "URL: %s %s\n"+ "Code: %d. Raw Message:\n\n%s", r.Request.Method, r.Request.URL.String(), r.StatusCode, bodyBuf.String()) } var errBody bytes.Buffer errBody.WriteString(fmt.Sprintf( "Error making API request.\n\n"+ "URL: %s %s\n"+ "Code: %d. Errors:\n\n", r.Request.Method, r.Request.URL.String(), r.StatusCode)) for _, err := range resp.Errors { errBody.WriteString(fmt.Sprintf("* %s", err)) } return fmt.Errorf(errBody.String()) }
// Verifies the integrity of the instance identity document using its SHA256 // RSA signature. After verification, returns the unmarshaled instance identity // document. func (b *backend) verifyInstanceIdentitySignature(s logical.Storage, identityBytes, signatureBytes []byte) (*identityDocument, error) { if len(identityBytes) == 0 { return nil, fmt.Errorf("missing instance identity document") } if len(signatureBytes) == 0 { return nil, fmt.Errorf("missing SHA256 RSA signature of the instance identity document") } // Get the public certificates that are used to verify the signature. // This returns a slice of certificates containing the default // certificate and all the registered certificates via // 'config/certificate/<cert_name>' endpoint, for verifying the RSA // digest. publicCerts, err := b.awsPublicCertificates(s, false) if err != nil { return nil, err } if publicCerts == nil || len(publicCerts) == 0 { return nil, fmt.Errorf("certificates to verify the signature are not found") } // Check if any of the certs registered at the backend can verify the // signature for _, cert := range publicCerts { err := cert.CheckSignature(x509.SHA256WithRSA, identityBytes, signatureBytes) if err == nil { var identityDoc identityDocument if decErr := jsonutil.DecodeJSON(identityBytes, &identityDoc); decErr != nil { return nil, decErr } return &identityDoc, nil } } return nil, fmt.Errorf("instance identity verification using SHA256 RSA signature is unsuccessful") }
// Cluster fetches the details of either local or global cluster based on the // input. This method errors out when Vault is sealed. func (c *Core) Cluster() (*Cluster, error) { var cluster Cluster // Fetch the storage entry. This call fails when Vault is sealed. entry, err := c.barrier.Get(coreLocalClusterInfoPath) if err != nil { return nil, err } if entry == nil { return &cluster, nil } // Decode the cluster information if err = jsonutil.DecodeJSON(entry.Value, &cluster); err != nil { return nil, fmt.Errorf("failed to decode cluster details: %v", err) } // Set in config file if c.clusterName != "" { cluster.Name = c.clusterName } return &cluster, nil }
// decodeLeaseEntry is used to reverse encode and return a new entry func decodeLeaseEntry(buf []byte) (*leaseEntry, error) { out := new(leaseEntry) return out, jsonutil.DecodeJSON(buf, out) }
// Leader is used to get the current active leader func (c *Core) Leader() (isLeader bool, leaderAddr string, err error) { c.stateLock.RLock() defer c.stateLock.RUnlock() // Check if HA enabled if c.ha == nil { return false, "", ErrHANotEnabled } // Check if sealed if c.sealed { return false, "", ErrSealed } // Check if we are the leader if !c.standby { // If we have connections from talking to a previous leader, close them // out to free resources if c.requestForwardingConnection != nil { c.requestForwardingConnectionLock.Lock() // Verify that the condition hasn't changed if c.requestForwardingConnection != nil { c.requestForwardingConnection.Transport.(*http.Transport).CloseIdleConnections() } c.requestForwardingConnection = nil c.requestForwardingConnectionLock.Unlock() } return true, c.redirectAddr, nil } // Initialize a lock lock, err := c.ha.LockWith(coreLockPath, "read") if err != nil { return false, "", err } // Read the value held, value, err := lock.Value() if err != nil { return false, "", err } if !held { return false, "", nil } // Value is the UUID of the leader, fetch the key key := coreLeaderPrefix + value entry, err := c.barrier.Get(key) if err != nil { return false, "", err } if entry == nil { return false, "", nil } entrySHA256 := sha256.Sum256(entry.Value) // Avoid JSON parsing and function calling if nothing has changed if c.clusterActiveAdvertisementHash != nil { if bytes.Compare(entrySHA256[:], c.clusterActiveAdvertisementHash) == 0 { return false, c.clusterActiveAdvertisement.RedirectAddr, nil } } var advAddr string var oldAdv bool var adv activeAdvertisement err = jsonutil.DecodeJSON(entry.Value, &adv) if err != nil { // Fall back to pre-struct handling advAddr = string(entry.Value) oldAdv = true } else { advAddr = adv.RedirectAddr } if !oldAdv { // Ensure we are using current values err = c.loadClusterTLS(adv) if err != nil { return false, "", err } // This will ensure that we both have a connection at the ready and that // the address is the current known value err = c.refreshRequestForwardingConnection(adv.ClusterAddr) if err != nil { return false, "", err } } c.clusterActiveAdvertisement = adv c.clusterActiveAdvertisementHash = entrySHA256[:] return false, advAddr, nil }
// Leader is used to get the current active leader func (c *Core) Leader() (isLeader bool, leaderAddr string, err error) { c.stateLock.RLock() defer c.stateLock.RUnlock() // Check if HA enabled if c.ha == nil { return false, "", ErrHANotEnabled } // Check if sealed if c.sealed { return false, "", ErrSealed } // Check if we are the leader if !c.standby { // If we have connections from talking to a previous leader, close them // out to free resources if c.requestForwardingConnection != nil { c.requestForwardingConnectionLock.Lock() // Verify that the condition hasn't changed if c.requestForwardingConnection != nil { c.requestForwardingConnection.transport.CloseIdleConnections() } c.requestForwardingConnection = nil c.requestForwardingConnectionLock.Unlock() } return true, c.redirectAddr, nil } // Initialize a lock lock, err := c.ha.LockWith(coreLockPath, "read") if err != nil { return false, "", err } // Read the value held, leaderUUID, err := lock.Value() if err != nil { return false, "", err } if !held { return false, "", nil } // If the leader hasn't changed, return the cached value; nothing changes // mid-leadership, and the barrier caches anyways if leaderUUID == c.clusterLeaderUUID && c.clusterLeaderRedirectAddr != "" { return false, c.clusterLeaderRedirectAddr, nil } key := coreLeaderPrefix + leaderUUID entry, err := c.barrier.Get(key) if err != nil { return false, "", err } if entry == nil { return false, "", nil } var oldAdv bool var adv activeAdvertisement err = jsonutil.DecodeJSON(entry.Value, &adv) if err != nil { // Fall back to pre-struct handling adv.RedirectAddr = string(entry.Value) oldAdv = true } if !oldAdv { // Ensure we are using current values err = c.loadClusterTLS(adv) if err != nil { return false, "", err } // This will ensure that we both have a connection at the ready and that // the address is the current known value err = c.refreshRequestForwardingConnection(adv.ClusterAddr) if err != nil { return false, "", err } } // Don't set these until everything has been parsed successfully or we'll // never try again c.clusterLeaderRedirectAddr = adv.RedirectAddr c.clusterLeaderUUID = leaderUUID return false, c.clusterLeaderRedirectAddr, nil }
// loadMounts is invoked as part of postUnseal to load the mount table func (c *Core) loadMounts() error { mountTable := &MountTable{} // Load the existing mount table raw, err := c.barrier.Get(coreMountConfigPath) if err != nil { c.logger.Error("core: failed to read mount table", "error", err) return errLoadMountsFailed } c.mountsLock.Lock() defer c.mountsLock.Unlock() if raw != nil { // Check if the persisted value has canary in the beginning. If // yes, decompress the table and then JSON decode it. If not, // simply JSON decode it. if err := jsonutil.DecodeJSON(raw.Value, mountTable); err != nil { c.logger.Error("core: failed to decompress and/or decode the mount table", "error", err) return err } c.mounts = mountTable } // Ensure that required entries are loaded, or new ones // added may never get loaded at all. Note that this // is only designed to work with singletons, as it checks // by type only. if c.mounts != nil { needPersist := false // Upgrade to typed mount table if c.mounts.Type == "" { c.mounts.Type = mountTableType needPersist = true } for _, requiredMount := range requiredMountTable().Entries { foundRequired := false for _, coreMount := range c.mounts.Entries { if coreMount.Type == requiredMount.Type { foundRequired = true break } } if !foundRequired { c.mounts.Entries = append(c.mounts.Entries, requiredMount) needPersist = true } } // Upgrade to table-scoped entries for _, entry := range c.mounts.Entries { if entry.Table == "" { entry.Table = c.mounts.Type needPersist = true } } // Done if we have restored the mount table and we don't need // to persist if !needPersist { return nil } } else { // Create and persist the default mount table c.mounts = defaultMountTable() } if err := c.persistMounts(c.mounts); err != nil { return errLoadMountsFailed } return nil }