Merge branch 'master' into ui-wizards-updates
This commit is contained in:
commit
9c0ae0bb35
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -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:
|
||||
|
||||
|
|
4
Makefile
4
Makefile
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}()
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -6,10 +6,5 @@ package physical;
|
|||
|
||||
message SealWrapEntry {
|
||||
bytes ciphertext = 1;
|
||||
|
||||
bytes iv = 2;
|
||||
|
||||
bytes hmac = 3;
|
||||
|
||||
bool wrapped = 4;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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"},
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)` |
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
```
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
```
|
|
@ -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.
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue