Merge branch 'master' into ui-wizards-updates

This commit is contained in:
Joshua Ogle 2018-09-04 13:15:30 -06:00 committed by GitHub
commit 9c0ae0bb35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 1202 additions and 236 deletions

View File

@ -1,3 +1,9 @@
## 0.11.1 (Unreleased)
BUG FIXES:
* secrets/pki: Fix sign-verbatim losing extra Subject attributes [GH-5245]
## 0.11.0 (August 28th, 2018)
DEPRECATIONS/CHANGES:
@ -5,7 +11,9 @@ DEPRECATIONS/CHANGES:
* Request Timeouts: A default request timeout of 90s is now enforced. This
setting can be overwritten in the config file. If you anticipate requests
taking longer than 90s this setting should be updated before upgrading.
* `sys/` Top Level Injection: For the last two years for backwards
* (NOTE: will be re-added into 0.11.1 as it broke more than anticipated. There
will be some further guidelines around when this will be removed again.)
* `sys/` Top Level Injection: For the last two years for backwards
compatibility data for various `sys/` routes has been injected into both the
Secret's Data map and into the top level of the JSON response object.
However, this has some subtle issues that pop up from time to time and is
@ -61,6 +69,9 @@ FEATURES:
* **HA Support for MySQL Storage**: MySQL storage now supports HA.
* **ACL Templating**: ACL policies can now be templated using identity Entity,
Groups, and Metadata.
* **UI Onboarding wizards**: The Vault UI can provide contextual help and
guidance, linking out to relevant links or guides on vaultproject.io for
various workflows in Vault.
IMPROVEMENTS:

View File

@ -147,10 +147,10 @@ proto:
protoc builtin/logical/database/dbplugin/*.proto --go_out=plugins=grpc:../../..
protoc logical/plugin/pb/*.proto --go_out=plugins=grpc:../../..
sed -i -e 's/Idp/IDP/' -e 's/Url/URL/' -e 's/Id/ID/' -e 's/EntityId/EntityID/' -e 's/Api/API/' -e 's/Qr/QR/' -e 's/protobuf:"/sentinel:"" protobuf:"/' helper/identity/types.pb.go helper/storagepacker/types.pb.go logical/plugin/pb/backend.pb.go
sed -i -e 's/Iv/IV/' -e 's/Hmac/HMAC/' physical/types.pb.go
fmtcheck:
@sh -c "'$(CURDIR)/scripts/gofmtcheck.sh'"
@true
#@sh -c "'$(CURDIR)/scripts/gofmtcheck.sh'"
fmt:
gofmt -w $(GOFMT_FILES)

View File

@ -286,13 +286,22 @@ func getAnyRegionForAwsPartition(partitionId string) *endpoints.Region {
}
const backendHelp = `
aws-ec2 auth method takes in PKCS#7 signature of an AWS EC2 instance and a client
created nonce to authenticates the EC2 instance with Vault.
The aws auth method uses either AWS IAM credentials or AWS-signed EC2 metadata
to authenticate clients, which are IAM principals or EC2 instances.
Authentication is backed by a preconfigured role in the backend. The role
represents the authorization of resources by containing Vault's policies.
Role can be created using 'role/<role>' endpoint.
Authentication of IAM principals, either IAM users or roles, is done using a
specifically signed AWS API request using clients' AWS IAM credentials. IAM
principals can then be assigned to roles within Vault. This is known as the
"iam" auth method.
Authentication of EC2 instances is done using either a signed PKCS#7 document
or a detached RSA signature of an AWS EC2 instance's identity document along
with a client-created nonce. This is known as the "ec2" auth method.
If there is need to further restrict the capabilities of the role on the instance
that is using the role, 'role_tag' option can be enabled on the role, and a tag
can be generated using 'role/<role>/tag' endpoint. This tag represents the

View File

@ -897,8 +897,8 @@ func (b *backend) handleRoleTagLogin(ctx context.Context, s logical.Storage, rol
}
return &roleTagLoginResponse{
Policies: rTag.Policies,
MaxTTL: rTag.MaxTTL,
Policies: rTag.Policies,
MaxTTL: rTag.MaxTTL,
DisallowReauthentication: rTag.DisallowReauthentication,
}, nil
}

View File

@ -860,11 +860,11 @@ func (r *awsRoleEntry) ToResponseData() map[string]interface{} {
"resolve_aws_unique_ids": r.ResolveAWSUniqueIDs,
"role_tag": r.RoleTag,
"allow_instance_migration": r.AllowInstanceMigration,
"ttl": r.TTL / time.Second,
"max_ttl": r.MaxTTL / time.Second,
"policies": r.Policies,
"disallow_reauthentication": r.DisallowReauthentication,
"period": r.Period / time.Second,
"ttl": r.TTL / time.Second,
"max_ttl": r.MaxTTL / time.Second,
"policies": r.Policies,
"disallow_reauthentication": r.DisallowReauthentication,
"period": r.Period / time.Second,
}
convertNilToEmptySlice := func(data map[string]interface{}, field string) {
@ -891,12 +891,12 @@ Create a role and associate policies to it.
const pathRoleDesc = `
A precondition for login is that a role should be created in the backend.
The login endpoint takes in the role name against which the instance
should be validated. After authenticating the instance, the authorization
for the instance to access Vault's resources is determined by the policies
that are associated to the role though this endpoint.
The login endpoint takes in the role name against which the client
should be validated. After authenticating the client, the authorization
to access Vault's resources is determined by the policies that are
associated to the role though this endpoint.
When the instances require only a subset of policies on the role, then
When an EC2 instance requires only a subset of policies on the role, then
'role_tag' option on the role can be enabled to create a role tag via the
endpoint 'role/<role>/tag'. This tag then needs to be applied on the
instance before it attempts a login. The policies on the tag should be a

View File

@ -574,12 +574,12 @@ func TestAwsEc2_RoleCrud(t *testing.T) {
"role_tag": "testtag",
"resolve_aws_unique_ids": false,
"allow_instance_migration": true,
"ttl": "10m",
"max_ttl": "20m",
"policies": "testpolicy1,testpolicy2",
"disallow_reauthentication": false,
"hmac_key": "testhmackey",
"period": "1m",
"ttl": "10m",
"max_ttl": "20m",
"policies": "testpolicy1,testpolicy2",
"disallow_reauthentication": false,
"hmac_key": "testhmackey",
"period": "1m",
}
roleReq.Path = "role/testrole"
@ -613,11 +613,11 @@ func TestAwsEc2_RoleCrud(t *testing.T) {
"resolve_aws_unique_ids": false,
"role_tag": "testtag",
"allow_instance_migration": true,
"ttl": time.Duration(600),
"max_ttl": time.Duration(1200),
"policies": []string{"testpolicy1", "testpolicy2"},
"disallow_reauthentication": false,
"period": time.Duration(60),
"ttl": time.Duration(600),
"max_ttl": time.Duration(1200),
"policies": []string{"testpolicy1", "testpolicy2"},
"disallow_reauthentication": false,
"period": time.Duration(60),
}
if !reflect.DeepEqual(expected, resp.Data) {
@ -676,9 +676,9 @@ func TestAwsEc2_RoleDurationSeconds(t *testing.T) {
"auth_type": "ec2",
"bound_iam_instance_profile_arn": "arn:aws:iam::123456789012:instance-profile/test-profile-name",
"resolve_aws_unique_ids": false,
"ttl": "10s",
"max_ttl": "20s",
"period": "30s",
"ttl": "10s",
"max_ttl": "20s",
"period": "30s",
}
roleReq := &logical.Request{

View File

@ -220,7 +220,7 @@ func TestBackend_PermittedDNSDomainsIntermediateCA(t *testing.T) {
// Sign the intermediate CSR using /pki
secret, err = client.Logical().Write("pki/root/sign-intermediate", map[string]interface{}{
"permitted_dns_domains": ".myvault.com",
"csr": intermediateCSR,
"csr": intermediateCSR,
})
if err != nil {
t.Fatal(err)

View File

@ -104,8 +104,8 @@ func (b *backend) pathConfigRead(ctx context.Context, req *logical.Request, d *f
resp := &logical.Response{
Data: map[string]interface{}{
"host": cfg.Host,
"port": cfg.Port,
"host": cfg.Host,
"port": cfg.Port,
"unregistered_user_policies": cfg.UnregisteredUserPolicies,
"dial_timeout": cfg.DialTimeout,
"read_timeout": cfg.ReadTimeout,

View File

@ -1961,8 +1961,8 @@ func TestBackend_SignSelfIssued(t *testing.T) {
Subject: pkix.Name{
CommonName: "foo.bar.com",
},
SerialNumber: big.NewInt(1234),
IsCA: false,
SerialNumber: big.NewInt(1234),
IsCA: false,
BasicConstraintsValid: true,
}
@ -1992,8 +1992,8 @@ func TestBackend_SignSelfIssued(t *testing.T) {
Subject: pkix.Name{
CommonName: "bar.foo.com",
},
SerialNumber: big.NewInt(2345),
IsCA: true,
SerialNumber: big.NewInt(2345),
IsCA: true,
BasicConstraintsValid: true,
}
ss, ssCert := getSelfSigned(template, issuer)
@ -2576,7 +2576,7 @@ func setCerts() {
NotBefore: time.Now().Add(-30 * time.Second),
NotAfter: time.Now().Add(262980 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
IsCA: true,
}
caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, cak.Public(), cak)
if err != nil {

View File

@ -82,7 +82,7 @@ func TestBackend_CA_Steps(t *testing.T) {
NotBefore: time.Now().Add(-30 * time.Second),
NotAfter: time.Now().Add(262980 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
IsCA: true,
}
caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, cak.Public(), cak)
if err != nil {

View File

@ -1380,6 +1380,7 @@ func signCertificate(data *dataBundle) (*certutil.ParsedCertBundle, error) {
if data.params.UseCSRValues {
certTemplate.Subject = data.csr.Subject
certTemplate.Subject.ExtraNames = certTemplate.Subject.Names
certTemplate.DNSNames = data.csr.DNSNames
certTemplate.EmailAddresses = data.csr.EmailAddresses

View File

@ -144,9 +144,6 @@ func TestServer_ReloadListener(t *testing.T) {
ui, cmd := testServerCommand(t)
_ = ui
finished := false
finishedMutex := sync.Mutex{}
wg.Add(1)
args := []string{"-config", td + "/reload.hcl"}
go func() {
@ -154,9 +151,6 @@ func TestServer_ReloadListener(t *testing.T) {
output := ui.ErrorWriter.String() + ui.OutputWriter.String()
t.Errorf("got a non-zero exit status: %s", output)
}
finishedMutex.Lock()
finished = true
finishedMutex.Unlock()
wg.Done()
}()

View File

@ -506,7 +506,7 @@ func setCerts() {
NotBefore: time.Now().Add(-30 * time.Second),
NotAfter: time.Now().Add(262980 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
IsCA: true,
}
caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey)
if err != nil {
@ -541,7 +541,7 @@ func setCerts() {
NotBefore: time.Now().Add(-30 * time.Second),
NotAfter: time.Now().Add(262980 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
IsCA: true,
}
intBytes, err := x509.CreateCertificate(rand.Reader, intCertTemplate, caCert, intKey.Public(), caKey)
if err != nil {

View File

@ -82,7 +82,7 @@ func TestHandler_cors(t *testing.T) {
"Access-Control-Allow-Origin": addr,
"Access-Control-Allow-Headers": strings.Join(vault.StdAllowedHeaders, ","),
"Access-Control-Max-Age": "300",
"Vary": "Origin",
"Vary": "Origin",
}
for expHeader, expected := range expHeaders {

View File

@ -20,8 +20,6 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type SealWrapEntry struct {
Ciphertext []byte `protobuf:"bytes,1,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"`
IV []byte `protobuf:"bytes,2,opt,name=iv,proto3" json:"iv,omitempty"`
HMAC []byte `protobuf:"bytes,3,opt,name=hmac,proto3" json:"hmac,omitempty"`
Wrapped bool `protobuf:"varint,4,opt,name=wrapped,proto3" json:"wrapped,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
@ -32,7 +30,7 @@ func (m *SealWrapEntry) Reset() { *m = SealWrapEntry{} }
func (m *SealWrapEntry) String() string { return proto.CompactTextString(m) }
func (*SealWrapEntry) ProtoMessage() {}
func (*SealWrapEntry) Descriptor() ([]byte, []int) {
return fileDescriptor_types_0f1d299b2a49592e, []int{0}
return fileDescriptor_types_80e2b3c13a71f106, []int{0}
}
func (m *SealWrapEntry) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SealWrapEntry.Unmarshal(m, b)
@ -59,20 +57,6 @@ func (m *SealWrapEntry) GetCiphertext() []byte {
return nil
}
func (m *SealWrapEntry) GetIV() []byte {
if m != nil {
return m.IV
}
return nil
}
func (m *SealWrapEntry) GetHMAC() []byte {
if m != nil {
return m.HMAC
}
return nil
}
func (m *SealWrapEntry) GetWrapped() bool {
if m != nil {
return m.Wrapped
@ -84,19 +68,18 @@ func init() {
proto.RegisterType((*SealWrapEntry)(nil), "physical.SealWrapEntry")
}
func init() { proto.RegisterFile("physical/types.proto", fileDescriptor_types_0f1d299b2a49592e) }
func init() { proto.RegisterFile("physical/types.proto", fileDescriptor_types_80e2b3c13a71f106) }
var fileDescriptor_types_0f1d299b2a49592e = []byte{
// 173 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0xce, 0xb1, 0x0a, 0xc2, 0x30,
0x10, 0xc6, 0x71, 0x5a, 0x8b, 0x96, 0x43, 0x1d, 0x82, 0x43, 0x26, 0x29, 0x8a, 0xd0, 0xa9, 0x19,
0x7c, 0x03, 0xc1, 0x17, 0xa8, 0x83, 0xe0, 0x76, 0x8d, 0xc1, 0x04, 0x5a, 0x73, 0xa4, 0xd7, 0x6a,
0xdf, 0x5e, 0x08, 0x14, 0xdc, 0xbe, 0xef, 0x37, 0xfd, 0x61, 0x47, 0x76, 0xea, 0x9d, 0xc6, 0x56,
0xf1, 0x44, 0xa6, 0xaf, 0x28, 0x78, 0xf6, 0x22, 0x9f, 0xf5, 0xd0, 0xc1, 0xe6, 0x66, 0xb0, 0xbd,
0x07, 0xa4, 0xeb, 0x9b, 0xc3, 0x24, 0xf6, 0x00, 0xda, 0x91, 0x35, 0x81, 0xcd, 0x97, 0x65, 0x52,
0x24, 0xe5, 0xba, 0xfe, 0x13, 0xb1, 0x85, 0xd4, 0x8d, 0x32, 0x8d, 0x9e, 0xba, 0x51, 0x08, 0xc8,
0x6c, 0x87, 0x5a, 0x2e, 0xa2, 0xc4, 0x2d, 0x24, 0xac, 0x3e, 0x01, 0x89, 0xcc, 0x53, 0x66, 0x45,
0x52, 0xe6, 0xf5, 0x7c, 0x2f, 0xa7, 0xc7, 0xf1, 0xe5, 0xd8, 0x0e, 0x4d, 0xa5, 0x7d, 0xa7, 0x2c,
0xf6, 0xd6, 0x69, 0x1f, 0x48, 0x8d, 0x38, 0xb4, 0xac, 0xe6, 0xaa, 0x66, 0x19, 0x33, 0xcf, 0xbf,
0x00, 0x00, 0x00, 0xff, 0xff, 0x8e, 0xe9, 0xa0, 0xf8, 0xbe, 0x00, 0x00, 0x00,
var fileDescriptor_types_80e2b3c13a71f106 = []byte{
// 148 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x29, 0xc8, 0xa8, 0x2c,
0xce, 0x4c, 0x4e, 0xcc, 0xd1, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9,
0x17, 0xe2, 0x80, 0x89, 0x2a, 0x79, 0x72, 0xf1, 0x06, 0xa7, 0x26, 0xe6, 0x84, 0x17, 0x25, 0x16,
0xb8, 0xe6, 0x95, 0x14, 0x55, 0x0a, 0xc9, 0x71, 0x71, 0x25, 0x67, 0x16, 0x64, 0xa4, 0x16, 0x95,
0xa4, 0x56, 0x94, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x21, 0x89, 0x08, 0x49, 0x70, 0xb1,
0x97, 0x17, 0x25, 0x16, 0x14, 0xa4, 0xa6, 0x48, 0xb0, 0x28, 0x30, 0x6a, 0x70, 0x04, 0xc1, 0xb8,
0x4e, 0xaa, 0x51, 0xca, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x19,
0x89, 0xc5, 0x19, 0x99, 0xc9, 0xf9, 0x45, 0x05, 0xfa, 0x65, 0x89, 0xa5, 0x39, 0x25, 0xfa, 0x30,
0x1b, 0x93, 0xd8, 0xc0, 0x4e, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x71, 0xf9, 0x7a, 0x09,
0x9a, 0x00, 0x00, 0x00,
}

View File

@ -6,10 +6,5 @@ package physical;
message SealWrapEntry {
bytes ciphertext = 1;
bytes iv = 2;
bytes hmac = 3;
bool wrapped = 4;
}

View File

@ -5,9 +5,9 @@
@docPath="/intro/getting-started/deploy.html#initializing-the-vault"
>
<p>
This is the very first step of setting
This is the very first step of setting up
a Vault server. Vault comes with an important
security feature called "seal", which lets you
security feature called a "seal", which lets you
shut down and secure your Vault installation if
there is a security breach. This is the default
state of Vault, so it is currently sealed since

View File

@ -73,9 +73,9 @@ type AESGCMBarrier struct {
// the provided physical backend for storage.
func NewAESGCMBarrier(physical physical.Backend) (*AESGCMBarrier, error) {
b := &AESGCMBarrier{
backend: physical,
sealed: true,
cache: make(map[uint32]cipher.AEAD),
backend: physical,
sealed: true,
cache: make(map[uint32]cipher.AEAD),
currentAESGCMVersionByte: byte(AESGCMVersion2),
}
return b, nil

View File

@ -25,46 +25,29 @@ func (c *Core) Capabilities(ctx context.Context, token, path string) ([]string,
return nil, &logical.StatusBadRequest{Err: "invalid token"}
}
if te.Policies == nil {
return []string{DenyCapability}, nil
}
var policies []*Policy
for _, tePolicy := range te.Policies {
policy, err := c.policyStore.GetPolicy(ctx, tePolicy, PolicyTypeToken)
if err != nil {
return nil, err
}
policies = append(policies, policy)
}
// Start with token entry policies
policies := te.Policies
// Fetch entity and entity group policies
entity, derivedPolicies, err := c.fetchEntityAndDerivedPolicies(te.EntityID)
if err != nil {
return nil, err
}
if entity != nil && entity.Disabled {
c.logger.Warn("permission denied as the entity on the token is disabled")
return nil, logical.ErrPermissionDenied
}
if te != nil && te.EntityID != "" && entity == nil {
if te.EntityID != "" && entity == nil {
c.logger.Warn("permission denied as the entity on the token is invalid")
return nil, logical.ErrPermissionDenied
}
for _, item := range derivedPolicies {
policy, err := c.policyStore.GetPolicy(ctx, item, PolicyTypeToken)
if err != nil {
return nil, err
}
policies = append(policies, policy)
}
policies = append(policies, derivedPolicies...)
if len(policies) == 0 {
return []string{DenyCapability}, nil
}
acl, err := NewACL(policies)
acl, err := c.policyStore.ACL(ctx, entity, policies...)
if err != nil {
return nil, err
}

View File

@ -2,6 +2,7 @@ package vault
import (
"context"
"fmt"
"reflect"
"sort"
"testing"
@ -115,6 +116,82 @@ path "secret/sample" {
}
}
func TestCapabilities_TemplatedPolicies(t *testing.T) {
var resp *logical.Response
var err error
i, _, c := testIdentityStoreWithGithubAuth(t)
// Create an entity and assign policy1 to it
entityReq := &logical.Request{
Path: "entity",
Operation: logical.UpdateOperation,
}
resp, err = i.HandleRequest(context.Background(), entityReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: resp: %#v\nerr: %#v\n", resp, err)
}
entityID := resp.Data["id"].(string)
// Create a token for the entity and assign policy2 on the token
ent := &logical.TokenEntry{
ID: "capabilitiestoken",
Path: "auth/token/create",
Policies: []string{"testpolicy"},
EntityID: entityID,
TTL: time.Hour,
}
testMakeTokenDirectly(t, c.tokenStore, ent)
tCases := []struct {
policy string
path string
expected []string
}{
{
`name = "testpolicy"
path "secret/{{identity.entity.id}}/sample" {
capabilities = ["update", "create"]
}
`,
fmt.Sprintf("secret/%s/sample", entityID),
[]string{"update", "create"},
},
{
`{"name": "testpolicy", "path": {"secret/{{identity.entity.id}}/sample": {"capabilities": ["read", "create"]}}}`,
fmt.Sprintf("secret/%s/sample", entityID),
[]string{"read", "create"},
},
{
`{"name": "testpolicy", "path": {"secret/sample": {"capabilities": ["read"]}}}`,
"secret/sample",
[]string{"read"},
},
}
for _, tCase := range tCases {
// Create the above policies
policy, err := ParseACLPolicy(tCase.policy)
if err != nil {
t.Fatalf("err: %v", err)
}
err = c.policyStore.SetPolicy(context.Background(), policy)
if err != nil {
t.Fatalf("err: %v", err)
}
actual, err := c.Capabilities(context.Background(), "capabilitiestoken", tCase.path)
if err != nil {
t.Fatalf("err: %v", err)
}
sort.Strings(actual)
sort.Strings(tCase.expected)
if !reflect.DeepEqual(actual, tCase.expected) {
t.Fatalf("bad: got\n%#v\nexpected\n%#v\n", actual, tCase.expected)
}
}
}
func TestCapabilities(t *testing.T) {
c, _, token := TestCoreUnsealed(t)

View File

@ -240,7 +240,7 @@ func (c *Core) setupCluster(ctx context.Context) error {
// 30 years of single-active uptime ought to be enough for anybody
NotAfter: time.Now().Add(262980 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
IsCA: true,
}
certBytes, err := x509.CreateCertificate(rand.Reader, template, template, c.localClusterPrivateKey.Load().(*ecdsa.PrivateKey).Public(), c.localClusterPrivateKey.Load().(*ecdsa.PrivateKey))

View File

@ -1114,7 +1114,7 @@ func (c *Core) sealInternalWithOptions(grabStateLock, keepHALock bool) error {
return nil
}
c.logger.Debug("marked as sealed")
c.logger.Info("marked as sealed")
// Clear forwarding clients
c.requestForwardingConnectionLock.Lock()

View File

@ -151,8 +151,8 @@ func TestIdentityStore_EntityCreateUpdate(t *testing.T) {
func TestIdentityStore_CloneImmutability(t *testing.T) {
alias := &identity.Alias{
ID: "testaliasid",
Name: "testaliasname",
ID: "testaliasid",
Name: "testaliasname",
MergedFromCanonicalIDs: []string{"entityid1"},
}

View File

@ -2179,7 +2179,7 @@ func (b *SystemBackend) handleTuneWriteCommon(ctx context.Context, path string,
changed = true
numBuiltIn++
// Special case to make sure we can not disable versioning once it's
// enabeled. If the vkv backend suports downgrading this can be removed.
// enabled. If the vkv backend suports downgrading this can be removed.
meVersion, err := parseutil.ParseInt(mountEntry.Options["version"])
if err != nil {
return nil, errwrap.Wrapf("unable to parse mount entry: {{err}}", err)

View File

@ -150,7 +150,7 @@ func (p *ACLPermissions) Clone() (*ACLPermissions, error) {
return ret, nil
}
// Parse is used to parse the specified ACL rules into an
// ParseACLPolicy is used to parse the specified ACL rules into an
// intermediary set of policies, before being compiled into
// the ACL
func ParseACLPolicy(rules string) (*Policy, error) {
@ -162,19 +162,6 @@ func ParseACLPolicy(rules string) (*Policy, error) {
// is templated so we don't check again, otherwise we check to see if it's a
// templated policy.
func parseACLPolicyWithTemplating(rules string, performTemplating bool, entity *identity.Entity, groups []*identity.Group) (*Policy, error) {
// Check for templating
var hasTemplating bool
var err error
if !performTemplating {
hasTemplating, _, err = identity.PopulateString(&identity.PopulateStringInput{
ValidityCheckOnly: true,
String: rules,
})
if err != nil {
return nil, errwrap.Wrapf("failed to validate policy templating: {{err}}", err)
}
}
// Parse the rules
root, err := hcl.Parse(rules)
if err != nil {
@ -200,7 +187,6 @@ func parseACLPolicyWithTemplating(rules string, performTemplating bool, entity *
var p Policy
p.Raw = rules
p.Type = PolicyTypeACL
p.Templated = hasTemplating || performTemplating
if err := hcl.DecodeObject(&p, list); err != nil {
return nil, errwrap.Wrapf("failed to parse policy: {{err}}", err)
}
@ -233,6 +219,17 @@ func parsePaths(result *Policy, list *ast.ObjectList, performTemplating bool, en
continue
}
key = templated
} else {
hasTemplating, _, err := identity.PopulateString(&identity.PopulateStringInput{
ValidityCheckOnly: true,
String: key,
})
if err != nil {
return errwrap.Wrapf("failed to validate policy templating: {{err}}", err)
}
if hasTemplating {
result.Templated = true
}
}
valid := []string{

View File

@ -311,9 +311,9 @@ func (c *Core) refreshRequestForwardingConnection(ctx context.Context, clusterAd
c.rpcClientConnCancelFunc = cancelFunc
c.rpcForwardingClient = &forwardingClient{
RequestForwardingClient: NewRequestForwardingClient(c.rpcClientConn),
core: c,
echoTicker: time.NewTicker(HeartbeatInterval),
echoContext: dctx,
core: c,
echoTicker: time.NewTicker(HeartbeatInterval),
echoContext: dctx,
}
c.rpcForwardingClient.startHeartbeat()

View File

@ -952,7 +952,7 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te
NotBefore: time.Now().Add(-30 * time.Second),
NotAfter: time.Now().Add(262980 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
IsCA: true,
}
caBytes, err = x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey)
if err != nil {

View File

@ -8,56 +8,88 @@ description: |-
# HTTP API
The Vault HTTP API gives you full access to Vault via HTTP. Every
aspect of Vault can be controlled via this API. The Vault CLI uses
the HTTP API to access Vault.
## Version Prefix
The Vault HTTP API gives you full access to Vault via HTTP. Every aspect of
Vault can be controlled via this API. The Vault CLI uses the HTTP API to access
Vault.
All API routes are prefixed with `/v1/`.
This documentation is only for the v1 API.
This documentation is only for the v1 API, which is currently the only version.
~> **Backwards compatibility:** At the current version, Vault does
not yet promise backwards compatibility even with the v1 prefix. We'll
remove this warning when this policy changes. We expect we'll reach API
stability by Vault 1.0.
~> **Backwards compatibility:** At the current version, Vault does not yet
promise backwards compatibility even with the v1 prefix. We'll remove this
warning when this policy changes. At this point in time the core API (that
is, `sys/` routes) change very infrequently, but various secrets engines/auth
methods/etc. sometimes have minor changes to accommodate new features as
they're developed.
## Transport
The API is expected to be accessed over a TLS connection at
all times, with a valid certificate that is verified by a well
behaved client. It is possible to disable TLS verification for
listeners, however, so API clients should expect to have to do both
depending on user settings.
The API is expected to be accessed over a TLS connection at all times, with a
valid certificate that is verified by a well-behaved client. It is possible to
disable TLS verification for listeners, however, so API clients should expect
to have to do both depending on user settings.
## Authentication
Once the Vault is unsealed, every other operation requires a _client token_. A
user may have a client token sent to her. The client token must be sent as the
`X-Vault-Token` HTTP header.
Once Vault is unsealed, almost every other operation requires a _client token_.
A user may have a client token sent to her. The client token must be sent as
the `X-Vault-Token` HTTP header.
Otherwise, a client token can be retrieved via [authentication
backends](/docs/auth/index.html).
Each auth method will have one or more unauthenticated login
endpoints. These endpoints can be reached without any authentication, and are
used for authentication itself. These endpoints are specific to each
auth method.
Each auth method has one or more unauthenticated login endpoints. These
endpoints can be reached without any authentication, and are used for
authentication to Vault itself. These endpoints are specific to each auth
method.
Login endpoints for auth methods that generate an identity will be
sent down via JSON. The resulting token should be saved on the client or passed
via the `X-Vault-Token` header for future requests.
Responses from auth login methods that generate an authentication token are
sent back to the client via JSON. The resulting token should be saved on the
client or passed via the `X-Vault-Token` header for future requests.
## Reading, Writing, and Listing Secrets
## Namespaces
Different backends implement different APIs according to their functionality.
The examples below are created with the `KVv1` backend, which acts like a
Key/Value store. Read the documentation for a particular backend for detailed
information on its API; this simply provides a general overview.
If using the [Namespaces](/docs/enterprise/namespaces/index.html) feature, API
operations are relative to the namespace value passed in via the
`X-Vault-Namespace` header. For instance, if the request path is to
`secret/foo`, and the header is set to `ns1/ns2/`, the final request path Vault
uses will be `ns1/ns2/secret/foo`. Note that it is semantically equivalent to
use a full path rather than the `X-Vault-Namespace` header, as the operation in
Vault will always look up the correct namespace based on the final given path.
Thus, it would be equivalent to the above example to set `X-Vault-Namespace` to
`ns1/` and a request path of `ns2/secret/foo`, or to not set
`X-Vault-Namespace` at all and use a request path of `ns1/ns2/secret/foo`.
Reading a secret via the HTTP API is done by issuing a GET using the
following URL:
For example, the following two commands result in equivalent requests:
```shell
$ curl \
-H "X-Vault-Token: f3b09679-3001-009d-2b80-9c306ab81aa6" \
-H "X-Vault-Namespace: ns1/ns2/" \
-X GET \
http://127.0.0.1:8200/v1/secret/foo
```
```shell
$ curl \
-H "X-Vault-Token: f3b09679-3001-009d-2b80-9c306ab81aa6" \
-X GET \
http://127.0.0.1:8200/v1/ns1/ns2/secret/foo
```
## API Operations
With few documented exceptions, all request body data and response data from
Vault is via JSON. Vault will set the `Content-Type` header appropriately but
does not require that clients set it.
Different plugins implement different APIs according to their functionality.
The examples below are created with the `KVv1` backend, which acts like a very
simple Key/Value store. Read the documentation for a particular backend for
detailed information on its API; this simply provides a general overview.
For `KVv1`, reading a secret via the HTTP API is done by issuing a GET:
```text
/v1/secret/foo
@ -75,8 +107,13 @@ $ curl \
http://127.0.0.1:8200/v1/secret/foo
```
A few endpoints consume query parameters via `GET` calls, but only if those
parameters are not sensitive, as some load balancers will log these. Most
endpoints that consume parameters use `POST` instead and put the parameters in
the request body.
You can list secrets as well. To do this, either issue a GET with the query
parameter `list=true`, or you can use the LIST HTTP verb. For the `kv`
parameter `list=true`, or you can use the `LIST` HTTP verb. For the `kv`
backend, listing is allowed on directories only, and returns the keys in the
given directory:
@ -87,10 +124,10 @@ $ curl \
http://127.0.0.1:8200/v1/secret/
```
The API documentation will use `LIST` as the HTTP ver, but you can still use
`GET` with the `?list=true` query string.
The API documentation uses `LIST` as the HTTP verb, but you can still use `GET`
with the `?list=true` query string.
To write a secret, issue a POST on the following URL:
To use an API that consumes data via request body, issue a `POST` or `PUT`:
```text
/v1/secret/foo
@ -115,19 +152,20 @@ $ curl \
http://127.0.0.1:8200/v1/secret/baz
```
Vault currently considers PUT and POST to be synonyms. Rather than trust a
Vault currently considers `PUT` and `POST` to be synonyms. Rather than trust a
client's stated intentions, Vault backends can implement an existence check to
discover whether an operation is actually a create or update operation based on
the data already stored within Vault.
the data already stored within Vault. This makes permission management via ACLs
more flexible.
For more examples, please look at the Vault API client.
## Help
To retrieve the help for any API within Vault, including mounted
backends, auth methods, etc. then append `?help=1` to any
URL. If you have valid permission to access the path, then the help text
will be returned with the following structure:
To retrieve the help for any API within Vault, including mounted backends, auth
methods, etc. then append `?help=1` to any URL. If you have valid permission to
access the path, then the help text will be returned with the following
structure:
```javascript
{
@ -153,26 +191,32 @@ or equal to 400.
## HTTP Status Codes
The following HTTP status codes are used throughout the API.
The following HTTP status codes are used throughout the API. Vault tries to
adhere to these whenever possible, but in some cases may not -- feel free to
file a bug in that case to point our attention to it!
- `200` - Success with data.
- `204` - Success, no data returned.
- `400` - Invalid request, missing or invalid data.
- `403` - Forbidden, your authentication details are either
incorrect, you don't have access to this feature, or - if CORS is
enabled - you made a cross-origin request from an origin that is
not allowed to make such requests.
- `404` - Invalid path. This can both mean that the path truly
doesn't exist or that you don't have permission to view a
specific path. We use 404 in some cases to avoid state leakage.
- `429` - Default return code for health status of standby nodes, indicating a
warning.
- `500` - Internal server error. An internal error has occurred,
try again later. If the error persists, report a bug.
- `503` - Vault is down for maintenance or is currently sealed.
Try again later.
- `403` - Forbidden, your authentication details are either incorrect, you
don't have access to this feature, or - if CORS is enabled - you made a
cross-origin request from an origin that is not allowed to make such
requests.
- `404` - Invalid path. This can both mean that the path truly doesn't exist or
that you don't have permission to view a specific path. We use 404 in some
cases to avoid state leakage.
- `429` - Default return code for health status of standby nodes. This will
likely change in the future.
- `473` - Default return code for health status of performance standby nodes.
- `500` - Internal server error. An internal error has occurred, try again
later. If the error persists, report a bug.
- `502` - A request to Vault required Vault making a request to a third party;
the third party responded with an error of some kind.
- `503` - Vault is down for maintenance or is currently sealed. Try again
later.
## Limits
A maximum request size of 32MB is imposed to prevent a denial
of service attack with arbitrarily large requests.
A maximum request size of 32MB is imposed to prevent a denial of service attack
with arbitrarily large requests; this can be tuned per `listener` block in
Vault's server configuration file.

View File

@ -962,6 +962,11 @@ This endpoint restores the backup as a named key. This will restore the key
configurations and all the versions of the named key along with HMAC keys. The
input to this endpoint should be the output of `/backup` endpoint.
~> For safety, the backend will refuse to restore to an existing key. If you
want to reuse a key name, you must delete the key before restoring. It is a
good idea to attempt restoring to a different key name first to verify that
the operation successfully completes.
| Method | Path | Produces |
| :------- | :-------------------------- | :--------------------- |
| `POST` | `/transit/restore(/:name)` | `204 (empty body)` |

View File

@ -26,6 +26,7 @@ The default status codes are:
- `200` if initialized, unsealed, and active
- `429` if unsealed and standby
- `472` if data recovery mode replication secondary and active
- `473` if performance standby
- `501` if not initialized
- `503` if sealed
@ -45,6 +46,9 @@ The default status codes are:
- `drsecondarycode` `(int: 472)` Specifies the status code that should be
returned for a DR secondary node.
- `performancestandbycode` `(int: 473)` Specifies the status code that should be
returned for a performance standby node.
- `sealedcode` `(int: 503)` Specifies the status code that should be returned
for a sealed node.
@ -72,6 +76,7 @@ standby of its status.
"initialized": true,
"sealed": false,
"standby": false,
"performance_standby": false,
"replication_perf_mode": "disabled",
"replication_dr_mode": "disabled",
"server_time_utc": 1516639589,

View File

@ -35,6 +35,8 @@ $ curl \
"ha_enabled": true,
"is_self": false,
"leader_address": "https://127.0.0.1:8200/",
"leader_cluster_address": "https://127.0.0.1:8201/"
"leader_cluster_address": "https://127.0.0.1:8201/",
"performance_standby": false,
"performance_standby_last_remote_wal": 0
}
```

BIN
website/source/assets/images/vault-acl-templating-2.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
website/source/assets/images/vault-acl-templating-3.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
website/source/assets/images/vault-acl-templating.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -24,8 +24,8 @@ same entry.
```text
$ vault login -method=userpass \
username=foo \
password=bar
username=mitchellh \
password=foo
```
### Via the API
@ -85,6 +85,5 @@ management tool.
## API
The Userpass auth method has a full HTTP API. Please see the
[Userpass auth method API](/api/auth/userpass/index.html) for more
details.
The Userpass auth method has a full HTTP API. Please see the [Userpass auth
method API](/api/auth/userpass/index.html) for more details.

View File

@ -148,14 +148,17 @@ The following parameters are used on backends that support [high availability][h
### Vault Enterprise Parameters
The following parameters are only used with Vault Enterprise
- `disable_sealwrap` `(bool: false)`  Disables using [seal wrapping][sealwrap]
for any value except the master key. If this value is toggled, the new
behavior will happen lazily (as values are read or written).
- `disable_performance_standby` `(bool: false)` If set, the node will not be
available to act as a performance standby node when not active.
- `disable_performance_standby` `(bool: false)` Specifies whether performance
standbys should be disabled on this node. Setting this to true on one Vault
node will disable this feature when this node is Active or Standby. It's
recomended to sync this setting across all nodes in the cluster.
The following parameters are only used with Vault Enterprise
[storage-backend]: /docs/configuration/storage/index.html
[listener]: /docs/configuration/listener/index.html
[seal]: /docs/configuration/seal/index.html

View File

@ -60,6 +60,40 @@ path "secret/foo" {
The above policy grants `read` access to `secret/foo` only after *both* the MFA
methods `dev_team_duo` and `sales_team_totp` are validated.
## Namespaces
All MFA configurations must be configured in the root namespace. They can be
referenced from ACL and Sentinel policies in any namespace via the method name
and can be tied to a mount accessor in any namespace.
When using [Sentinel
EGPs](/docs/enterprise/sentinel/index.html#endpoint-governing-policies-egps-),
any MFA configuration specified must be satisfied by all requests affected by
the policy, which can be difficult if the configured paths spread across
namespaces. One way to address this is to use a policy similar to the
following, using `or` operators to allow MFA configurations tied to mount
accessors in the various namespaces:
```python
import "mfa"
has_mfa = rule {
mfa.methods.duons1.valid
}
has_mfa2 = rule {
mfa.methods.duons2.valid
}
main = rule {
has_mfa or has_mfa2
}
```
When using TOTP, any user with ACL permissions can self-generate credentials.
Admins can generate or destroy credentials only if the targeted entity is in
the same namespace.
## Supplying MFA Credentials
MFA credentials are retrieved from the `X-Vault-MFA` HTTP header. The format of

View File

@ -44,20 +44,22 @@ Namespaces are isolated environments that functionally exist as "Vaults within a
They have separate login paths and support creating and managing data isolated to their
namespace. This data includes the following:
- Secret Engine Mounts
- Secret Engines
- Auth Methods
- Policies
- Identities (Entities, Groups)
- Tokens
Namespaces can also be configured to inherit all of this data from a higher *parent* namespace.
This simplifies the deployment of new namespaces, and can be combined with sentinel policies
to prescribe organization-wide infosec policies on tenants.
Rather than rely on Vault system admins, namespaces can be managed by delegated admins who
can be prescribed administration rights for their namespace. These delegated admins can also
create their own child namespaces, thereby prescribing admin rights on a subordinate group
of delegate admins.
Child namespaces can share policies from their parent namespaces. For example, a child namespace
may refer to parent identities (entities and groups) when writing policies that function only
within that child namespace. Similarly, a parent namespace can have policies asserted on child
identities.
## Setup and Best Practices
A [deployment guide](/guides/operations/multi-tenant.html) is available to help guide you

View File

@ -0,0 +1,90 @@
---
layout: "docs"
page_title: "Performance Standby Nodes - Vault Enterprise"
sidebar_current: "docs-vault-enterprise-perf-standbys"
description: |-
Performance Standby Nodes - Vault Enterprise
---
# Performance Standby Nodes
Vault supports a multi-server mode for high availability. This mode protects
against outages by running multiple Vault servers. High availability mode
is automatically enabled when using a data store that supports it. You can
learn more about HA mode on the [Concepts](/docs/concepts/ha.html) page.
Vault Enterprise offers additional features that allow HA nodes to service
read-only requests on the local standby node. Read-only requests are requests
that do not modify Vault's storage.
## Server-to-Server Communication
Performance Standbys require the request forwarding method described in the [HA
Server-to-Server](/docs/concepts/ha.html#server-to-server-communication) docs.
A performance standby will connect to the active node over the existing request
forwarding connection. If selected by the active node to be promoted to a
performance standby it will be handed a newly-generated private key and certificate
for use in creating a new mutually-authenticated TLS connection to the cluster
port. This connection will be used to send updates from the active node to the
standby.
## Request Forwarding
A Performance Standby will attempt to process requests that come in. If a
storage write is detected the standby will forward the request over the cluster
port connection to the active node. If the request is read-only the Performance
Standby will handle the requests locally.
Sending requests to Performance Stanbys that result in forwarded writes will be
slightly slower than going directly to the active node. A client that has
advanced knowledge of the behavior of the call can choose to point the request
to the appropriate node.
### Direct Access
A Performance Standby will tag itself as such in consul if service registration
is enabled. To access the set of Performance Standbys the `performance-standby`
tag can be used. For example to send requets to only the performance standbys
`https://performance-standby.vault.dc1.consul` could be used (host name may vary
based on consul configuration).
### Behind Load Balancers
Additionally, if you wish to point your load balancers at performance standby
nodes, the `sys/health` endpoint can be used to determine if a node is a
performance standby. See the [sys/health API](/api/system/health.html) docs for
more info.
## Disabling Performance Standbys
To disable performance standbys the `disable_performance_standby` flag should be
set to true in the Vault config file. This will both tell a standby not to
attempt to enable performance mode and an active node to not allow any
performance standby connections.
This setting should be synced across all nodes in the cluster.
## Monitoring Performance Standbys
To verify your node is a performance standby the `vault status` command can be
used:
```
$ vault status
Key Value
--- -----
Seal Type shamir
Sealed false
Total Shares 1
Threshold 1
Version 0.11.0+prem
Cluster Name vault-cluster-d040e74c
Cluster ID 9f82e03b-71fb-97a6-9c5a-46fa6715d6e4
HA Enabled true
HA Cluster https://127.0.0.1:8201
HA Mode standby
Active Node Address http://127.0.0.1:8200
Performance Standby Node true
Performance Standby Last Remote WAL 380329
```

View File

@ -47,3 +47,22 @@ then one of the standbys will take over and become the active instance.
It is important to note that only _unsealed_ servers act as a standby.
If a server is still in the sealed state, then it cannot act as a standby
as it would be unable to serve any requests should the active server fail.
# Performance Standby Nodes (Enterprise)
Performance Standby Nodes are just like traditional High Availability standby
nodes but they can service read-only requests from users or applications.
Read-only requests are requests that do not modify Vault's storage. This allows
for Vault to quickly scale its ability to service these kinds of operations,
providing near-linear request-per-second scaling in many common scenarios for
some secrets engines like K/V and Transit. By spreading traffic across
performance standby nodes, clients can scale these IOPS horizontally to handle
extremely high traffic workloads.
If a request comes into a Performance Standby Node that causes a storage write
the request will be forwarded onto the active server. If the request is
read-only the request will be serviced locally on the Performance Standby.
Just like traditional HA standbys if the active node is sealed, fails, or loses
newtwork connectivity then a performance standby can take over and become the
active instance.

View File

@ -81,9 +81,9 @@ key_type otp
### Establish an SSH session
```text
$ ssh username@localhost
$ ssh username@x.x.x.x
Password: <Enter OTP>
username@ip:~$
username@x.x.x.x:~$
```
### Automate it!

View File

@ -623,9 +623,9 @@ exists on the virtual machine.
![AppRole auth method workflow](/assets/images/vault-approle-workflow2.png)
Secret ID is like a password. To keep the Secret ID confidential, use
[**response wrapping**](/docs/concepts/response-wrapping.html) so that only the
expected client can unwrap the Secret ID.
The secret ID can be delivered using [**response
wrapping**](/docs/concepts/response-wrapping.html) to transmit the _reference_
to the secret ID rather than the actual value.
In [Step 3](#step3), you executed the following command to retrieve the Secret
ID:
@ -673,7 +673,7 @@ b07d7a47-1d0d-741d-20b4-ae0de7c6d964
Read the [_AppRole with Terraform and
Chef_](/guides/identity/approle-trusted-entities.html) guide to better
understand the role of trusted entities using Terraform and Chef as an example.
understand the role of trusted entities using Terraform and Chef as an example.
To learn more about response wrapping, go to the [Cubbyhole Response
Wrapping](/guides/secret-mgmt/cubbyhole.html) guide.

View File

@ -20,6 +20,9 @@ Role-Based Access Control (RBAC) by specifying access privileges. Authoring of
policies is probably the first step the Vault administrator performs. This guide
walks you through creating example policies for `admin` and `provisioner` users.
- [ACL Policy Templating](/guides/identity/policy-templating.html) guide
demonstrates templated policy paths to allow non-static paths.
- [AppRole Pull Authentication](/guides/identity/authentication.html) guide
that introduces the steps to generate tokens for machines or apps by enabling
AppRole auth method.

View File

@ -0,0 +1,613 @@
---
layout: "guides"
page_title: "ACL Policy Templating - Guides"
sidebar_current: "guides-identity-policy-templating"
description: |-
As of 0.11, ACL policies support templating to allow non-static policy paths.
---
# ACL Policy Templating
Vault operates on a **secure by default** standard, and as such, an empty policy
grants **no permissions** in the system. Therefore, policies must be created to
govern the behavior of clients and instrument Role-Based Access Control (RBAC)
by specifying access privileges (_authorization_).
Since everything in Vault is path based, policy authors must be aware of
all existing paths as well as paths to be created.
The [Policies](/guides/identity/policies.html) guide walks you through the
creation of ACL policies in Vault.
-> This guide highlights the use of ACL templating which was introduced in
**Vault 0.11**.
## Reference Material
- [Templated Policies](/docs/concepts/policies.html#templated-policies)
- [Policy API](/api/system/policy.html)
- [Identity Secrets Engine](/docs/secrets/identity/index.html)
- [Identity: Entities and Groups](/guides/identity/identity.html)
## Estimated Time to Complete
10 minutes
## Challenge
The only way to specify non-static paths in ACL policies was to use globs (`*`)
at the end of paths.
```hcl
path "transit/keys/*" {
capabilities = [ "read" ]
}
path "secret/webapp_*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
```
This makes many management and delegation tasks challenging. For example,
allowing a user to change their own password by invoking the
`auth/userpass/users/<user_name>/password` endpoint can require either a policy
for _every user_ or requires the use of Sentinel which is a part of [Vault
Enterprise](/docs/enterprise/sentinel/index.html).
## Solution
As of **Vault 0.11**, ACL templating capability is available to allow a subset
of user information to be used within ACL policy paths.
-> **NOTE:** This feature leverages [Vault
Identities](/docs/secrets/identity/index.html) to inject values into ACL policy
paths.
## Prerequisites
To perform the tasks described in this guide, you need to have an environment
with **Vault 0.11** or later. Refer to the [Getting
Started](/intro/getting-started/install.html) guide to install Vault.
Alternately, you can use the [Vault
Playground](https://www.katacoda.com/hashicorp/scenarios/vault-playground)
environment.
~> This guide assumes that you know how to create ACL policies. If you don't,
go through the interactive [Policy
tutorial](https://www.katacoda.com/hashicorp/scenarios/vault-policies) or
[Policies](/guides/identity/policies.html) guide first.
### Policy requirements
Since this guide demonstrates the creation of an `admin` policy, log in with the
`root` token if possible. Otherwise, refer to the policy requirement in the
[Policies](/guides/identity/policies.html#policy-requirements) guide.
## Steps
Assume that the following policy requirements were given:
- Each _user_ can perform all operations on their allocated key/value secret
path (`user-kv/data/<user_name>`)
- The education _group_ has a dedicated key/value secret store for each region where
all operations can be performed by the group members
(`group-kv/data/education/<region>`)
- The _group_ members can update the group information such as metadata about
the group (`identity/group/id/<group_id>`)
In this guide, you are going to perform the following steps:
1. [Write templated ACL policies](#step1)
1. [Deploy your policy](#step2)
1. [Setup an entity and a group](#step3)
1. [Test the ACL templating](#step4)
### <a name="step1"></a>Step 1: Write templated ACL policies
Policy authors can pass in a policy path containing double curly braces as
templating delimiters: `{{<parameter>}}`.
#### Available Templating Parameters
| Name | Description |
| :--------------------------------------------------------------------- | :--------------------------------------------------------------------------- |
| `identity.entity.id` | The entity's ID |
| `identity.entity.name` | The entity's name |
| `identity.entity.metadata.<<metadata key>>` | Metadata associated with the entity for the given key |
| `identity.entity.aliases.<<mount accessor>>.id` | Entity alias ID for the given mount |
| `identity.entity.aliases.<<mount accessor>>.name` | Entity alias name for the given mount |
| `identity.entity.aliases.<<mount accessor>>.metadata.<<metadata key>>` | Metadata associated with the alias for the given mount and metadata key |
| `identity.groups.ids.<<group id>>.name` | The group name for the given group ID |
| `identity.groups.names.<<group name>>.id` | The group ID for the given group name |
| `identity.groups.names.<<group id>>.metadata.<<metadata key>>` | Metadata associated with the group for the given key |
| `identity.groups.names.<<group name>>.metadata.<<metadata key>>` | Metadata associated with the group for the given key |
-> **NOTE:** Identity groups are not directly attached to a token and an entity
can be associated with multiple groups. Therefore, in order to reference a
group, the **group ID** or **group name** must be provided (e.g.
`identity.groups.ids.59f001d5-dd49-6d63-51e4-357c1e7a4d44.name`).
Example:
This policy allows users to change their own password given that the username
and password are defined in the `userpass` auth method.
```hcl
path "auth/userpass/users/{{identity.entity.aliases.auth_userpass_6671d643.name}}/password" {
capabilities = [ "update" ]
}
```
#### Write the following policies:
User template (`user-tmpl.hcl`)
```hcl
# Grant permissions on user specific path
path "user-kv/data/{{identity.entity.name}}/*" {
capabilities = [ "create", "update", "read", "delete", "list" ]
}
# For Web UI usage
path "user-kv/metadata" {
capabilities = ["list"]
}
```
Group template (`group-tmpl.hcl`)
```hcl
# Grant permissions on the group specific path
# The region is specified in the group metadata
path "group-kv/data/education/{{identity.groups.names.education.metadata.region}}/*" {
capabilities = [ "create", "update", "read", "delete", "list" ]
}
# Group member can update the group information
path "identity/group/id/{{identity.groups.names.education.id}}" {
capabilities = [ "update", "read" ]
}
# For Web UI usage
path "group-kv/metadata" {
capabilities = ["list"]
}
path "identity/group/id" {
capabilities = [ "list" ]
}
```
### <a name="step2"></a>Step 2: Deploy your policy
- [CLI command](#step2-cli)
- [API call using cURL](#step2-api)
- [Web UI](#step2-ui)
#### <a name="step2-cli"></a>CLI command
```shell
# Create the user-tmpl policy
$ vault policy write user-tmpl user-tmpl.hcl
# Create the group-tmpl policy
$ vault policy write group-tmpl group-tmpl.hcl
```
#### <a name="step2-api"></a>API call using cURL
To create a policy, use the `/sys/policies/acl` endpoint:
```sh
$ curl --header "X-Vault-Token: <TOKEN>" \
--request PUT \
--data <PAYLOAD> \
<VAULT_ADDRESS>/v1/sys/policies/acl/<POLICY_NAME>
```
Where `<TOKEN>` is your valid token, and `<PAYLOAD>` includes the policy name and
stringified policy.
Example:
```shell
# API request payload for user-tmpl
$ tee payload_user.json <<EOF
{
"policy": "path "user-kv/data/{{identity.entity.name}}/*" {\n capabilities = [ "create", "update", "read", "delete", "list" ]\n } ..."
}
EOF
# Create user-tmpl policy
$ curl --header "X-Vault-Token: ..." \
--request PUT
--data @payload_user.json \
http://127.0.0.1:8200/v1/sys/policies/acl/user-tmpl
# API request payload for group-tmpl
$ tee payload_group.json <<EOF
{
"policy": "path "group-kv/data/{{identity.group.id}}/*" {\n capabilities = [ "create", "update", "read", "delete", "list" ]\n }"
}
EOF
# Create group-tmpl policy
$ curl --header "X-Vault-Token: ..." \
--request PUT
--data @payload_group.json \
http://127.0.0.1:8200/v1/sys/policies/acl/group-tmpl
```
#### <a name="step2-ui"></a>Web UI
Open a web browser and launch the Vault UI (e.g. http://127.0.0.1:8200/ui) and
then login.
1. Click the **Policies** tab, and then select **Create ACL policy**.
1. Toggle **Upload file**, and click **Choose a file** to select the
`user-tmpl.hcl` file you wrote at [Step 1](#step1).
![Create Policy](/assets/images/vault-ctrl-grp-2.png)
This loads the policy and sets the **Name** to `user-tmpl`.
1. Click the **Create Policy** button.
1. Repeat the steps to create the `group-tmpl` policy.
### <a name="step3"></a>Step 3: Setup an entity and a group
Let's create an entity, **`bob_smith`** with a user **`bob`** as its entity
alias. Also, create a group, **`education`** and add the **`bob_smith`** entity
as its group member.
![Entity & Group](/assets/images/vault-acl-templating.png)
-> This step only demonstrates CLI commands and Web UI to create
entities and groups. Refer to the [Identity - Entities and
Groups](/guides/identity/identity.html) guide if you need the full details.
- [CLI command](#step3-cli)
- [Web UI](#step3-ui)
#### <a name="step3-cli"></a>CLI command
The following command uses [`jq`](https://stedolan.github.io/jq/download/) tool
to parse JSON output.
```shell
# Enable userpass
$ vault auth enable userpass
# Create a user, bob
$ vault write auth/userpass/users/bob password="training"
# Retrieve the userpass mount accessor and save it in a file named, accessor.txt
$ vault auth list -format=json | jq -r '.["userpass/"].accessor' > accessor.txt
# Create bob_smith entity and save the identity ID in the entity_id.txt
$ vault write -format=json identity/entity name="bob_smith" policies="user-tmpl" \
| jq -r ".data.id" > entity_id.txt
# Add an entity alias for the bob_smith entity
$ vault write identity/entity-alias name="bob" \
canonical_id=$(cat entity_id.txt) \
mount_accessor=$(cat accessor.txt)
# Finally, create education group and add bob_smith entity as a member
# Save the generated group ID in the group_id.txt file
$ vault write -format=json identity/group name="education" \
policies="group-tmpl" \
metadata=region="us-west" \
member_entity_ids=$(cat entity_id.txt) \
| jq -r ".data.id" > group_id.txt
```
#### <a name="step3-ui"></a>Web UI
1. Click the **Access** tab, and select **Enable new method**.
1. Select **Username & Password** from the **Type** drop-down menu.
1. Click **Enable Method**.
1. Click the Vault CLI shell icon (**`>_`**) to open a command shell. Enter the
following command to create a new user, **`bob`**.
```plaintext
$ vault write auth/userpass/users/bob password="training"
```
![Create Policy](/assets/images/vault-ctrl-grp-3.png)
1. Click the icon (**`>_`**) again to hide the shell.
1. From the **Access** tab, select **Entities** and then **Create entity**.
1. Enter **`bob_smith`** in the **Name** field and enter **`user-tmpl`** in the
**Policies** filed.
1. Click **Create**.
1. Select **Add alias**. Enter **`bob`** in the **Name** field and select
**`userpass/ (userpass)`** from the **Auth Backend** drop-down list.
1. Select the **`bob_smith`** entity and copy its **ID** displayed under the
**Details** tab.
1. Click **Groups** from the left navigation, and select **Create group**.
1. Enter **`education`** in the **Name**, and enter **`group-tmpl`** in the
**Policies** fields. Under **Metadata**, enter **`region`** as a key and
**`us-west`** as the key value. Enter the `bob_smith` entity ID in the **Member
Entity IDs** field.
![Group](/assets/images/vault-acl-templating-2.png)
1. Click **Create**.
### <a name="step4"></a>Step 4: Test the ACL templating
- [CLI command](#step4-cli)
- [API call using cURL](#step4-api)
- [Web UI](#step4-ui)
#### <a name="step4-cli"></a>CLI Command
1. Enable key/value v2 secrets engine at `user-kv` and `group-kv` paths.
```plaintext
$ vault secrets enable -path=user-kv kv-v2
$ vault secrets enable -path=group-kv kv-v2
```
1. Log in as **`bob`**.
```plaintext
$ vault login -method=userpass username="bob" password="training"
Key Value
--- -----
token 5f2b2594-f0b4-0a7b-6f51-767345091dcc
token_accessor 78b652dd-4320-f18f-b882-0732b7ae9ac9
token_duration 768h
token_renewable true
token_policies ["default"]
identity_policies ["group-tmpl" "user-tmpl"]
policies ["default" "group-tmpl" "user-tmpl"]
token_meta_username bob
```
1. Remember that `bob` is a member of the `bob_smith` entity; therefore, the
"`user-kv/data/{{identity.entity.name}}/*`" expression in the `user-tmpl` policy
translates to "**`user-kv/data/bob_smith/*`**". Let's test!
```plaintext
$ vault kv put user-kv/bob_smith/apikey webapp="12344567890"
Key Value
--- -----
created_time 2018-08-30T18:28:30.845345444Z
deletion_time n/a
destroyed false
version 1
```
1. The region was set to `us-west` for the `education` group that the
`bob_smith` belongs to. Therefore, the
"`group-kv/data/education/{{identity.groups.names.education.metadata.region}}/*`"
expression in the `group-tmpl` policy translates to
"**`group-kv/data/education/us-west/*`**". Let's verify.
```plaintext
$ vault kv put group-kv/education/us-west/db_cred password="ABCDEFGHIJKLMN"
Key Value
--- -----
created_time 2018-08-30T18:29:02.023749491Z
deletion_time n/a
destroyed false
version 1
```
1. Verify that you can update the group information. The `group-tmpl` policy
permits "update" and "read" on the
"`identity/group/id/{{identity.groups.names.education.id}}`" path. In [Step
2](#step2), you saved the `education` group ID in the `group_id.txt` file.
```plaintext
$ vault write identity/group/id/$(cat group_id.txt) \
policies="group-tmpl" \
metadata=region="us-west" \
metadata=contact_email="james@example.com"
```
Read the group information to verify that the data has been updated.
```plaintext
$ vault read identity/group/id/$(cat group_id.txt)
Key Value
--- -----
alias map[]
creation_time 2018-08-29T20:38:49.383960564Z
id d6ee454e-915a-4bef-9e43-4ffd7762cd4c
last_update_time 2018-08-29T22:52:42.005544616Z
member_entity_ids [1a272450-d147-c3fd-63ae-f16b65b5ee02]
member_group_ids <nil>
metadata map[contact_email:james@example.com region:us-west]
modify_index 3
name education
parent_group_ids <nil>
policies [group-tmpl]
type internal
```
#### <a name="step4-api"></a>API call using cURL
1. Enable key/value v2 secrets engine at `user-kv` and `group-kv` paths.
```plaintext
$ tee payload.json <<EOF
{
"type": "kv",
"options": {
"version": "2"
}
}
EOF
$ curl --header "X-Vault-Token: ..." \
--request POST \
--data @payload.json \
https://127.0.0.1:8200/v1/sys/mounts/user-kv
$ curl --header "X-Vault-Token: ..." \
--request POST \
--data @payload.json \
https://127.0.0.1:8200/v1/sys/mounts/group-kv
```
1. Log in as **`bob`**.
```plaintext
$ curl --request POST \
--data '{"password": "training"}' \
http://127.0.0.1:8200/v1/auth/userpass/login/bob | jq
```
Copy the generated **`client_token`** value for `bob`.
1. Remember that `bob` is a member of the `bob_smith` entity; therefore, the
"`user-kv/data/{{identity.entity.name}}/*`" expression in the `user-tmpl` policy
translates to "**`user-kv/data/bob_smith/*`**". Let's test!
```plaintext
$ curl --header "X-Vault-Token: <bob_client_token>" \
--request POST \
--data '{ "data": {"webapp": "12344567890"} }' \
http://127.0.0.1:8200/v1/user-kv/data/bob_smith/apikey
```
1. The region was set to `us-west` for the `education` group that the
`bob_smith` belongs to. Therefore, the
"`group-kv/data/education/{{identity.groups.names.education.metadata.region}}/*`"
expression in the `group-tmpl` policy translates to
"**`group-kv/data/education/us-west/*`**". Let's verify.
```plaintext
$ curl --header "X-Vault-Token: <bob_client_token>" \
--request POST \
--data '{ "data": {"password": "ABCDEFGHIJKLMN"} }' \
http://127.0.0.1:8200/v1/group-kv/data/education/us-west/db_cred
```
1. Verify that you can update the group information. The `group-tmpl` policy
permits "update" and "read" on the
"`identity/group/id/{{identity.groups.names.education.id}}`" path.
```plaintext
$ tee group_info.json <<EOF
{
"metadata": {
"region": "us-west",
"contact_email": "james@example.com"
},
"policies": "group-tmpl"
}
EOF
$ curl --header "X-Vault-Token: <bob_client_token>" \
--request POST \
--data @group_info.json \
http://127.0.0.1:8200/v1/identity/group/id/<education_group_id>
```
Where the group ID is the ID returned in [Step 2](#step2). (NOTE: If you performed
Step 2 using the CLI commands, the group ID is stored in the `group_id.txt`
file. If you performed the tasks via Web UI, copy the `education` group ID
from UI.)
Read the group information to verify that the data has been updated.
```plaintext
$ curl --header "X-Vault-Token: <bob_client_token>" \
http://127.0.0.1:8200/v1/identity/group/id/<education_group_id>
```
#### <a name="step4-ui"></a>Web UI
1. In **Secrets** tab, select **Enable new engine**.
1. Select the radio-button for **KV**, and then click **Next**.
1. Enter **`user-kv`** in the path field, and then select **2** for KV
version.
1. Click **Enable Engine**.
1. Return to **Secrets** and then select **Enable new engine** again.
1. Select the radio-button for **KV**, and then click **Next**.
1. Enter **`group-kv`** in the path field, and then select **2** for KV
version.
1. Click **Enable Engine**.
1. Now, sign out as the current user so that you can log in as `bob`. ![Sign
off](/assets/images/vault-acl-templating-3.png)
1. In the Vault sign in page, select **Username** and then enter **`bob`** in
the **Username** field, and **`training`** in the **Password** field.
1. Click **Sign in**.
1. Remember that `bob` is a member of the `bob_smith` entity; therefore, the
"`user-kv/data/{{identity.entity.name}}/*`" expression in the `user-tmpl` policy
translates to "**`user-kv/data/bob_smith/*`**". Select **`user-kv`** secrets
engine, and then select **Create secret**.
1. Enter **`bob_smith/apikey`** in the **PATH FOR THIS SECRET** field,
**`webapp`** in the key field, and **`12344567890`** in its value field.
1. Click **Save**. You should be able to perform this successfully.
1. The region was set to `us-west` for the `education` group that the
`bob_smith` belongs to. Therefore, the
"`group-kv/data/education/{{identity.groups.names.education.metadata.region}}/*`"
expression in the `group-tmpl` policy translates to
"**`group-kv/data/education/us-west/*`**". From the **Secrets** tab, select
**`group-kv`** secrets engine, and then select **Create secret**.
1. Enter **`education/us-west/db_cred`** in the **PATH FOR THIS SECRET** field.
Enter **`password`** in the key field, and **`ABCDEFGHIJKLMN`** in its value
field.
1. Click **Save**. You should be able to perform this successfully.
1. To verify that you can update the group information which is allowed by the
"`identity/group/id/{{identity.groups.names.education.id}}`" expression in the
`group-tmpl` policy, select the **Access** tab.
1. Select **Groups**, and then **`education`**.
1. Select **Edit group**. Add a new metadata where the key is
**`contact_email`** and its value is **`james@example.com`**.
1. Click **Save**. The group metadata should be successfully updated.
## Next steps
To learn about Sentinel policies to implement finer-grained policies, refer to
the [Sentinel Policies](/guides/identity/sentinel.html) guide.

View File

@ -19,6 +19,10 @@ through use of a reference architecture. This example is to convey a general
architecture, which is likely to be adapted to accommodate the specific needs of
each implementation.
- [Vault Deployment Guide](/guides/operations/deployment-guide.html) covers the
steps required to install and configure a single HashiCorp Vault cluster as
defined in the Vault Reference Architecture.
- [Vault HA with Consul](/guides/operations/vault-ha-consul.html) guide
walks you through a simple Vault HA cluster implementation which is backed by
[HashiCorp Consul](https://www.consul.io/intro/index.html).

View File

@ -14,7 +14,7 @@ Everything in Vault is path-based, and often uses the terms `path` and
`namespace` interchangeably. The application namespace pattern is a useful
construct for providing Vault as a service to internal customers, giving them
the ability to implement secure multi-tenancy within Vault in order to provide
isolation and ensure teams can self-manage their own environments.
isolation and ensure teams can self-manage their own environments.
## Reference Material
@ -446,6 +446,8 @@ over.
-> This step only demonstrates CLI commands and Web UI to create
entities and groups. Refer to the [Identity - Entities and
Groups](/guides/identity/identity.html) guide if you need the full details.
Also, read the [Additional Discussion](#additional-discussion) section for
an example of setting up external groups.
#### CLI Command
@ -817,10 +819,11 @@ $ curl --header "X-Vault-Token: 5YNNjDDl6D8iW3eGQIlU0q.9dKXw" \
1. Open a web browser and launch the Vault UI (e.g. http://127.0.01:8200/ui). If
you are already logged in, sign out.
1. At the **Sign in to Vault**, set the **Namespace** to **`education/training`**.
1. At the **Sign in to Vault**, set the **Namespace** to
**`education/training`**.
1. Select the **Userpass** tab, and enter **`bsmith`** in the **Username** field,
and **`password`** in the **Password** field.
1. Select the **Userpass** tab, and enter **`bsmith`** in the **Username**
field, and **`password`** in the **Password** field.
1. Click **Sign in**.
@ -837,7 +840,6 @@ and **`password`** in the **Password** field.
1. Click **Enable Engine** to finish.
<br>
~> **Summary:** As this guide demonstrated, each namespace you created behaves
@ -847,6 +849,62 @@ Tokens, policies, and secrets engines are tied to its namespace; therefore, each
client must acquire a valid token for each namespace to access their secrets.
## Additional Discussion
For the simplicity, this guide used the username and password (`userpass`) auth
method which was enabled at the education namespace. However, most likely, your
organization uses LDAP auth method which is enabled in the root namespace
instead.
In such as case, here are the steps to create the "Training Admin" group as
described in this guide.
1. Enable and configure the desired auth method (e.g. LDAP) in the root
namespace.
```plaintext
$ vault auth enable ldap
$ vault write auth/ldap/config \
url="ldap://ldap.example.com" \
userdn="ou=Users,dc=example,dc=com" \
groupdn="ou=Groups,dc=example,dc=com" \
groupfilter="(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))" \
groupattr="cn" \
upndomain="example.com" \
certificate=@ldap_ca_cert.pem \
insecure_tls=false \
starttls=true
```
1. Create an _external_ group in the root namespace.
```shell
# Get the mount accessor for ldap auth method and save it in accessor.txt file
$ vault auth list -format=json \
| jq -r '.["ldap/"].accessor' > accessor.txt
# Create an external group and save the generated group ID in group_id.txt
$ vault write -format=json identity/group name="training_admin_root" \
type="external" \
| jq -r ".data.id" > group_id.txt
# Create a group alias - assuming that the group name in LDAP is "ops_training"
$ vault write -format=json identity/group-alias name="ops_training" \
mount_accessor=$(cat accessor.txt) \
canonical_id=$(cat group_id.txt)
```
1. In the `education/training` namespace, create an _internal_ group which has
the external group (`training_admin_root`) as its member.
```plaintext
$ vault write -namespace=education/training identity/group \
name="Training Admin" \
policies="training-admin" \
member_group_ids=$(cat group_id.txt)
```
## Next steps
Refer to the [Sentinel Policies](/guides/identity/sentinel.html) guide if you

View File

@ -79,7 +79,7 @@ CPU" in AWS terms, such as T-series instances.
| Size | CPU | Memory | Disk | Typical Cloud Instance Types |
|-------|----------|-----------------|-----------|--------------------------------------------|
| Small | 2 core | 4-8 GB RAM | 25 GB | **AWS:** m5.large |
| | | | | **Azure:** Standard_A2_v2, Standard_A4_v2 |
| | | | | **Azure:** Standard_D2_v3 |
| | | | | **GCE:** n1-standard-2, n1-standard-4 |
| Large | 4-8 core | 16-32 GB RAM | 50 GB | **AWS:** m5.xlarge, m5.2xlarge |
| | | | | **Azure:** Standard_D4_v3, Standard_D8_v3 |
@ -90,10 +90,10 @@ CPU" in AWS terms, such as T-series instances.
| Size | CPU | Memory | Disk | Typical Cloud Instance Types |
|-------|----------|-----------------|-----------|--------------------------------------------|
| Small | 2 core | 8-16 GB RAM | 50 GB | **AWS:** m5.large, m5.xlarge |
| | | | | **Azure:** Standard_A4_v2, Standard_A8_v2 |
| | | | | **Azure:** Standard_D2_v3, Standard_D4_v3 |
| | | | | **GCE:** n1-standard-4, n1-standard-8 |
| Large | 4-8 core | 32-64+ GB RAM | 100 GB | **AWS:** m5.2xlarge, m5.4xlarge |
| | | | | **Azure:** Standard_D4_v3, Standard_D5_v3 |
| | | | | **Azure:** Standard_D4_v3, Standard_D8_v3 |
| | | | | **GCE:** n1-standard-16, n1-standard-32 |
### Hardware Considerations

View File

@ -25,11 +25,20 @@ redirect requests to the _active_ node.
![Reference Architecture](/assets/images/vault-ha-consul-3.png)
> **NOTE:** As of version **0.11**, those standby nodes can handle most
read-only requests and behave as read-replica nodes. This **Performance Standby
Nodes** feature is included in _Vault Enterprise Premium_, and also available
for _Vault Enterprise Pro_ with additional fee. This is particularly useful for
processing high volume Encryption as a Service ([Transit secrets
engine](/docs/secrets/transit/index.html)) requests. Read [Performance Standby
Nodes](/docs/enterprise/performance-standby/index.html) documentation for more
details.
~> This guide will walk you through a simple Vault Highly Available (HA) cluster
implementation. While this is not an exhaustive or prescriptive guide that can
be used as a drop-in production example, it covers the **basics** enough to inform
your own production setup.
be used as a drop-in production example, it covers the **basics** enough to
inform your own production setup.
## Reference Materials

View File

@ -10,12 +10,23 @@ description: |-
# Overview
This page contains the list of deprecations and important or breaking changes
for Vault 0.11.0 Beta compared to 0.10.0. Please read it carefully.
for Vault 0.11.0 compared to 0.10.0. Please read it carefully.
**NOTE** This beta release does not have a forward compatibility guarantee and
certain functionality may change that will be incompatible with the General
Availability release. Please only use the beta releases to test functionality
and upgrades with clusters that can be lost.
## Known Issues
### Nomad Integration
Users that integrate Vault with Nomad should hold off on upgrading. A modification to
Vault's API is causing a runtime issue with the Nomad to Vault integration.
### Minified JSON Policies
Users that generate policies in minfied JSON may cause a parsing errors due to
a regression in the policy parser when it encounters repeating brackets. Although
HCL is the official language for policies in Vault, HCL is JSON compatible and JSON
should work in place of HCL. To work around this error, pretty print the JSON policies
or add spaces between repeating brackets. This regression will be addressed in
a future release.
## Changes Since 0.10.4
@ -49,7 +60,7 @@ provided there.
### Performance Standbys On By Default
If you flavor/license of Vault Enterprise supports Performance Standbys, they
If your flavor/license of Vault Enterprise supports Performance Standbys, they
are on by default. You can disable this behavior per-node with the
`disable_performance_standby` configuration flag.
@ -91,7 +102,7 @@ the `/aws/sts/<role_name>` endpoint).
## Full List Since 0.10.0
### Revocations of dynamic secrets leases now asynchronous
### Revocations of dynamic secrets leases now asynchronous
Dynamic secret lease revocation are now queued/asynchronous rather
than synchronous. This allows Vault to take responsibility for revocation
@ -106,7 +117,7 @@ The CLI will no longer retry commands on 5xx errors. This was a
source of confusion to users as to why Vault would "hang" before returning a
5xx error. The Go API client still defaults to two retries.
### Identity Entity Alias metadata
### Identity Entity Alias metadata
You can no longer manually set metadata on
entity aliases. All alias data (except the canonical entity ID it refers to)

View File

@ -154,7 +154,7 @@
<a href="/api/auth/gcp/index.html">Google Cloud</a>
</li>
<li<%= sidebar_current("docs-http-auth-jwt") %>>
<a href="/api/auth/jwt/index.html">JWT/OIDC</a>
<a href="/api/auth/jwt/index.html">JWT</a>
</li>
<li<%= sidebar_current("docs-http-auth-kubernetes") %>>
<a href="/api/auth/kubernetes/index.html">Kubernetes</a>

View File

@ -393,7 +393,7 @@
<a href="/docs/agent/autoauth/methods/gcp.html">GCP</a>
</li>
<li<%= sidebar_current("docs-agent-autoauth-methods-jwt") %>>
<a href="/docs/agent/autoauth/methods/jwt.html">JWT/OIDC</a>
<a href="/docs/agent/autoauth/methods/jwt.html">JWT</a>
</li>
<li<%= sidebar_current("docs-agent-autoauth-methods-kubernetes") %>>
<a href="/docs/agent/autoauth/methods/kubernetes.html">Kubernetes</a>
@ -664,9 +664,12 @@
<li<%= sidebar_current("docs-vault-enterprise-sealwrap")%>>
<a href="/docs/enterprise/sealwrap/index.html">Seal Wrap / FIPS 140-2</a>
</li>
<li<%= sidebar_current("docs-vault-enterprise-namespaces")%>>
<li<%= sidebar_current("docs-vault-enterprise-namespaces")%>>
<a href="/docs/enterprise/namespaces/index.html">Namespaces</a>
</li>
<li <%= sidebar_current("docs-vault-enterprise-performance-standbys")%>>
<a href="/docs/enterprise/performance-standby/index.html">Performance Standbys</a>
</li>
<li<%= sidebar_current("docs-vault-enterprise-control-groups") %>>
<a href="/docs/enterprise/control-groups/index.html">Control Groups</a>
</li>

View File

@ -65,6 +65,9 @@
<li<%= sidebar_current("guides-identity-policies") %>>
<a href="/guides/identity/policies.html">Policies</a>
</li>
<li<%= sidebar_current("guides-identity-policy-templating") %>>
<a href="/guides/identity/policy-templating.html">ACL Policy Templating</a>
</li>
<li<%= sidebar_current("guides-identity-authentication") %>>
<a href="/guides/identity/authentication.html">AppRole Pull Authentication</a>
</li>