Files
ubicloud/spec/db_spec.rb
Jeremy Evans 0cd7749d9f Check all encrypted columns are redacted
Also check that redacted columns are unique.
2025-07-17 00:44:14 +09:00

142 lines
5.5 KiB
Ruby

# frozen_string_literal: true
RSpec.describe "Database" do
it "has no unexpectedly collated columns" do
collated_columns = DB[:pg_class]
.join(:pg_namespace, oid: :relnamespace) { |j| Sequel.qualify(j, :nspname) !~ ["pg_catalog", "information_schema"] }
.join(:pg_attribute, attrelid: Sequel[:pg_class][:oid])
.join(:pg_collation, oid: :attcollation) { |j| Sequel.qualify(j, :collcollate) !~ "C" }
.select_map(Sequel.join(%i[nspname relname attname].map { Sequel.function(:quote_ident, it) }, ".").as(:name))
expect(collated_columns).to eq []
end
it "has no encrypted columns that are not redacted" do
Sequel::Model.subclasses.each do |mod|
next unless (md = mod.instance_variable_get(:@column_encryption_metadata))
keys = md.keys
next if keys.empty?
expect(mod.redacted_columns & keys).to eq keys
end
end
it "has unique redacted columns" do
Sequel::Model.subclasses.each do |mod|
next unless (md = mod.instance_variable_get(:@column_encryption_metadata))
keys = md.keys
next if keys.empty?
expect(mod.redacted_columns.uniq).to eq mod.redacted_columns
end
end
describe "audit_log table" do
def insert_row(at)
DB[:audit_log].returning(:ubid_type).insert(at:, ubid_type: "vm", action: "create", project_id: Project.generate_uuid, subject_id: Account.generate_uuid, object_ids: Sequel.pg_array([], :uuid))
end
it "inserts row for current date without error" do
expect(insert_row(Date.today)).to eq [{ubid_type: "vm"}]
end
it "needs new partitions (action required)" do
# if this test starts to fail, it's time to create new partitions for table audit_log. if this is ignored,
# DB[:audit_log].insert will start to fail in 45 days or less.
# Add a warning 60 days out, so the issue can be fixed before the warning turns into an test failure.
begin
DB.transaction(savepoint: true) do
insert_row(Time.now + 60 * 60 * 24 * 60)
end
rescue Sequel::ConstraintViolation
warn "\n\nNEED TO CREATE MORE audit_log PARTITIONS!\n\n\n"
end
expect(insert_row(Time.now + 60 * 60 * 24 * 45)).to eq [{ubid_type: "vm"}]
end
it "fails to create in the past" do
expect { insert_row(Date.new(2025, 4)) }.to raise_error(Sequel::ConstraintViolation)
end
it "fails to create in the distant future" do
expect { insert_row(Time.now + 60 * 60 * 24 * 365 * 10) }.to raise_error(Sequel::ConstraintViolation)
end
end
describe "NetAddr extensions" do
it "converts inet/cidr columns to NetAddr objects" do
expect(DB.get(Sequel.cast("127.0.0.1", :inet))).to be_a NetAddr::IPv4
expect(DB.get(Sequel.cast("127.0.0.0/8", :cidr))).to be_a NetAddr::IPv4Net
expect(DB.get(Sequel.cast("::1", :inet))).to be_a NetAddr::IPv6
expect(DB.get(Sequel.cast("fe80::/16", :cidr))).to be_a NetAddr::IPv6Net
end
it "converts inet/cidr array columns to arrays of NetAddr objects" do
expect(DB.get(Sequel.pg_array([Sequel.cast("127.0.0.1", :inet)])).first).to be_a NetAddr::IPv4
expect(DB.get(Sequel.pg_array([Sequel.cast("127.0.0.0/8", :cidr)])).first).to be_a NetAddr::IPv4Net
expect(DB.get(Sequel.pg_array([Sequel.cast("::1", :inet)])).first).to be_a NetAddr::IPv6
expect(DB.get(Sequel.pg_array([Sequel.cast("fe80::/16", :cidr)])).first).to be_a NetAddr::IPv6Net
end
it "supports NetAddr objects in dataset filters" do
expect(DB.get(NetAddr::IPv4.parse("127.0.0.1"))).to be_a NetAddr::IPv4
expect(DB.get(NetAddr::IPv4Net.parse("127.0.0.0/8"))).to be_a NetAddr::IPv4Net
expect(DB.get(NetAddr::IPv6.parse("::1"))).to be_a NetAddr::IPv6
expect(DB.get(NetAddr::IPv6Net.parse("fe80::/16"))).to be_a NetAddr::IPv6Net
end
it "typecasts cidr columns to NetAddr objects" do
address = Address.new(routed_to_host_id: "46683a25-acb1-4371-afe9-d39f303e44b4")
address.cidr = "127.0.0.0/8"
expect(address.cidr).to be_a NetAddr::IPv4Net
address.cidr = NetAddr::IPv4.parse("127.0.0.1")
expect(address.cidr).to be_a NetAddr::IPv4Net
address.cidr = NetAddr::IPv4Net.parse("127.0.0.0/30")
expect(address.cidr).to be_a NetAddr::IPv4Net
expect(address.valid?).to be true
address.cidr = "fe80::/8"
expect(address.cidr).to be_a NetAddr::IPv6Net
address.cidr = NetAddr::IPv6.parse("::1")
expect(address.cidr).to be_a NetAddr::IPv6Net
expect(address.cidr.to_s).to eq "::1/128"
address.cidr = NetAddr::IPv6Net.parse("fe80::/16")
expect(address.cidr).to be_a NetAddr::IPv6Net
expect(address.valid?).to be true
address.cidr = "10"
expect(address.cidr).to eq "10"
expect(address.valid?).to be false
address.cidr = 10
expect(address.cidr).to eq 10
expect(address.valid?).to be false
end
it "typecasts inet columns to NetAddr objects" do
host = Prog::Vm::HostNexus.assemble("127.0.0.1").subject
host.ip6 = "127.0.0.1"
expect(host.ip6).to be_a NetAddr::IPv4
host.ip6 = NetAddr::IPv4.parse("127.0.0.1")
expect(host.ip6).to be_a NetAddr::IPv4
expect(host.valid?).to be true
host.ip6 = "::1"
expect(host.ip6).to be_a NetAddr::IPv6
host.ip6 = NetAddr::IPv6.parse("::1")
expect(host.ip6).to be_a NetAddr::IPv6
expect(host.valid?).to be true
host.ip6 = "127.0.0.0/8"
expect(host.ip6).to eq "127.0.0.0/8"
expect(host.valid?).to be false
host.ip6 = 10
expect(host.ip6).to eq 10
expect(host.valid?).to be false
end
end
end