Introduction
This article explains how to limit the size of keys written to the KV Secrets Engine (version 2) using a Sentinel policy.
Prerequisites
- Sentinel requires Vault Enterprise.
Use Case
- Restrict the key-value size for KV secrets before writing to storage by using a Sentinel policy.
Procedure
The following steps will create an Endpoint Governing Sentinel Policy that restricts the value size to 10 characters.
1. Create a file calledmax-kv-value-size.sentinel
that contains the Sentinel policy:
# EGP policy meant for path secret/(data/)?.*
# Restrict KV values to a certain size
check_size = func(key, value) {
# Set your size here
max_value_size = 10
if (length(value) > max_value_size) {
print(key, "value size of", length(value), "exceeds limit of", max_value_size)
return 1
} else {
print(key, "value size of", length(value), "is within limit of", max_value_size)
return 0
}
}
check_kvs = func() {
# Make sure there is request data
if length(request.data else 0) is 0 {
print("No request data")
return false
}
# Make sure there is a data object
if "data" not in keys(request.data) {
print("No data object")
return false
}
# Debug data
print("DATA:", request.data.data)
# Iterate through all K/V pairs
fails = 0
for request.data.data as key, value {
#print("KEY:", key)
#print("VALUE:", value)
fails += check_size(key, value)
}
# Return false if any failures were counted
if fails > 0 {
print(fails, "failures!")
return false
}
return true
}
# Rule applies to creating/updating/patching K/V pairs
precond = rule {
request.operation in ["create", "update"]
}
# Main rule
main = rule when precond {
check_kvs()
}
2. Store the Base64-encoded max-kv-value-size.sentinel
policy in an environment variable named POLICY
:
$ POLICY=$(base64 max-kv-value-size.sentinel)
3. Create a policy called maxkv
with an enforcement level of hard-mandatory to restrict the size of keys written to KV-v2 secrets:
$ vault write sys/policies/egp/maxkv policy="${POLICY}" paths="secret/*" enforcement_level="hard-mandatory"
Success! Data written to: sys/policies/egp/maxkv
4. Review the policy to confirm that the Sentinel policy has been registered correctly:
$ vault read sys/policies/egp/maxkv
Key Value
--- -----
enforcement_level hard-mandatory
name maxkv
paths [secret/*]
policy # EGP policy meant for path secret/(data/)?.*
# Restrict KV values to a certain size
check_size = func(key, value) {
# Set your size here
max_value_size = 10
if (length(value) > max_value_size) {
print(key, "value size of", length(value), "exceeds limit of", max_value_size)
return 1
} else {
print(key, "value size of", length(value), "is within limit of", max_value_size)
return 0
}
}
check_kvs = func() {
# Make sure there is request data
if length(request.data else 0) is 0 {
print("No request data")
return false
}
# Make sure there is a data object
if "data" not in keys(request.data) {
print("No data object")
return false
}
# Debug data
print("DATA:", request.data.data)
# Iterate through all K/V pairs
fails = 0
for request.data.data as key, value {
#print("KEY:", key)
#print("VALUE:", value)
fails += check_size(key, value)
}
# Return false if any failures were counted
if fails > 0 {
print(fails, "failures!")
return false
}
return true
}
# Rule applies to creating/updating/patching K/V pairs
precond = rule {
request.operation in ["create", "update"]
}
# Main rule
main = rule when precond {
check_kvs()
}
Test the policy
The policy must be tested using a non-root token, as root tokens are exempt from Sentinel policy checks. In this example, a token with the admin policy attached will be used:
1. Create a token with admin
policy
$ vault token create -policy=admin
Key Value
--- -----
token s.g8**********************
token_accessor JVf****************
token_duration 768h
token_renewable true
token_policies ["admin" "default"]
identity_policies []
policies ["admin" "default"]
$ vault login s.g8***************
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token s.g8*******************
token_accessor JVf****************
token_duration 767h59m44s
token_renewable true
token_policies ["admin" "default"]
identity_policies []
policies ["admin" "default"]
2. Attempt to write a secret to the path secret/
with a length greater than 10 characters. This will be prohibited due to the Sentinel policy set:
$ vault kv put secret/test target=thisismysecret
Error writing data to secret/data/test: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/secret/data/test
Code: 403. Errors:
* 2 errors occurred:
* egp standard policy "root/maxkv" evaluation resulted in denial.
The specific error was:
<nil>
A trace of the execution for policy "root/maxkv" is available:
Result: false
Description: EGP policy meant for path secret/(data/)?.*
Restrict KV values to a certain size
print() output:
DATA: {"target": "thisismysecret"}
target value size of 14 exceeds limit of 10
1 failures!
Rule "main" (byte offset 1184) = false
Rule "precond" (byte offset 1109) = true
* permission denied
3. Write a secret to the path secret/
with a length shorter than 10 characters. This will comply with the assigned Sentinel policy and successfully write the secret:
$ vault kv put secret/test target=thisismy
Key Value
--- -----
created_time 2022-04-07T13:27:06.593245Z
deletion_time n/a
destroyed false
version 2