コード例 #1
0
ファイル: duo_test.go プロジェクト: quixoten/vault
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
}
コード例 #2
0
ファイル: format_json_test.go プロジェクト: quixoten/vault
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))
		}
	}
}
コード例 #3
0
ファイル: keyring.go プロジェクト: quixoten/vault
// 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
}
コード例 #4
0
ファイル: logical_cubbyhole.go プロジェクト: quixoten/vault
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
}
コード例 #5
0
ファイル: duo_test.go プロジェクト: quixoten/vault
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)
	}
}
コード例 #6
0
ファイル: path_roles.go プロジェクト: quixoten/vault
// 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
}
コード例 #7
0
ファイル: auth.go プロジェクト: mhurne/vault
// 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
}
コード例 #8
0
ファイル: rekey.go プロジェクト: mhurne/vault
// 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
}
コード例 #9
0
ファイル: forwarded_request.go プロジェクト: mhurne/vault
// 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
}
コード例 #10
0
ファイル: helpers.go プロジェクト: quixoten/vault
// 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"}
}
コード例 #11
0
ファイル: logical_passthrough.go プロジェクト: quixoten/vault
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
}
コード例 #12
0
ファイル: audit.go プロジェクト: nawien-sharma/vault
// 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
}
コード例 #13
0
ファイル: backend_test.go プロジェクト: quixoten/vault
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
		},
	}
}
コード例 #14
0
ファイル: path_login.go プロジェクト: quixoten/vault
// 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
}
コード例 #15
0
ファイル: seal.go プロジェクト: nawien-sharma/vault
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
}
コード例 #16
0
ファイル: policy.go プロジェクト: chrishoffman/vault
// 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
}
コード例 #17
0
ファイル: format_test.go プロジェクト: quixoten/vault
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)
	}
}
コード例 #18
0
ファイル: path_struct.go プロジェクト: quixoten/vault
// 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
}
コード例 #19
0
ファイル: wal.go プロジェクト: quixoten/vault
// 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
}
コード例 #20
0
ファイル: keyring.go プロジェクト: quixoten/vault
// 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
}
コード例 #21
0
ファイル: policy.go プロジェクト: chrishoffman/vault
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
}
コード例 #22
0
ファイル: util.go プロジェクト: quixoten/vault
// 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)
}
コード例 #23
0
ファイル: lock_manager.go プロジェクト: chrishoffman/vault
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
}
コード例 #24
0
ファイル: response.go プロジェクト: achanda/nomad
// 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())
}
コード例 #25
0
ファイル: path_login.go プロジェクト: quixoten/vault
// 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")
}
コード例 #26
0
ファイル: cluster.go プロジェクト: quixoten/vault
// 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
}
コード例 #27
0
ファイル: expiration.go プロジェクト: naunga/vault
// 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)
}
コード例 #28
0
ファイル: core.go プロジェクト: mhurne/vault
// 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
}
コード例 #29
0
ファイル: core.go プロジェクト: chrishoffman/vault
// 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
}
コード例 #30
0
ファイル: mount.go プロジェクト: nawien-sharma/vault
// 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
}