Validate the size of the value for instance level variables
Summary
Instance level variables have a limit of 1024
characters for the encrypted_value
attribute, set at the database level, but no validation on the Rails side for the size of the value
:
Ci::InstanceVariable.validators
# => [#<ActiveRecord::Validations::PresenceValidator:0x00007fef077ba270 @attributes=[:key], @options={}>,
#<ActiveRecord::Validations::LengthValidator:0x00007fef077b9668 @attributes=[:key], @options={:maximum=>255}>,
#<ActiveModel::Validations::FormatValidator:0x00007fef077b8c18 @attributes=[:key], @options={:with=>/\A[a-zA-Z0-9_]+\z/, :message=>"can contain only letters, digits and '_'."}>,
#<ActiveRecord::Validations::UniquenessValidator:0x00007feee5827518
@attributes=[:key],
@klass=Ci::InstanceVariable(id: integer, variable_type: integer, masked: boolean, protected: boolean, key: text, encrypted_value: text, encrypted_value_iv: text, value: ),
@options={:message=>"(%{value}) has already been taken"}>,
#<ActiveModel::Validations::InclusionValidator:0x00007fef077f8318 @attributes=[:masked], @delimiter=[true, false], @options={:in=>[true, false]}>,
#<ActiveModel::Validations::FormatValidator:0x00007feee580f008 @attributes=[:value], @options={:if=>:masked?, :with=>/\A[a-zA-Z0-9_+=\/@:.-]{8,}\z/}>]
Trying to save any encrypted_value
above 1024
characters is going to result in a 500
error.
Steps to reproduce
curl --header "PRIVATE-TOKEN: token" "http://localhost:3000/api/v4/admin/ci/variables" --request POST --form "key=NEW_VARIABLE" --form "value=$(openssl rand -hex 512)"
{"message":"500 Internal Server Error"}
Possible fixes
We must add a validation for value
size and make sure that the encrypted_value
size for the value
is under the database limit.
The size of encrypted_value
is the size of value
plus the size of the initialization vector(16) plus the overhead of base64 serialization, so the maximum value that we can store is about 735
characters. We could set the validation limit to 700
as extra precaution.
I think the best long term solution is to use a bytea
column to store the encrypted attributes. I think this would yield ~35%
in storage reduction.