Introduction
This article shows how to use a Sentinel policy to restrict the size of keys written to KVv2 secrets.
Prerequisites
- Vault Enterprise
Configuration
- Create a file called
max-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()
}
- Store the Base64 encoded
max-kv-value-size.sentinel
policy in an environment variable named POLICY
$ POLICY=$(base64 max-kv-value-size.sentinel)
- Create a policy called
maxkv
with enforcement level of hard-mandatory to restricts the size of keys written to KVv2 secrets
$ vault write sys/policies/egp/maxkv policy="${POLICY}" paths="secret/*" enforcement_level="hard-mandatory"
Success! Data written to: sys/policies/egp/maxkv
- Read the policy to validate Sentinel policy 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 needs to be tested for a non-root token because root tokens are not subject to Sentinel policy checks. In this example it will be used with a token that has the admin policy attached:
- 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"]
- try to write a secret to the path
secret/
with length higher than 10 and this will not be allowed:
$ 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
- write a secret to the path
secret/
with a shorter length and this is successful:
$ 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