feat(db): LDAP Credential Library operational entities

This commit is contained in:
Andrew Gaffney authored and Danielle Miu committed 2025-11-05 16:20:13 -05:00
1 parent 548782a261
commit f4d81e0026
6 files changed
+338 -9

No files matched your search

@@ -0,0 +1,253 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: BUSL-1.1
begin;
create table credential_vault_ldap_library (
public_id wt_public_id primary key,
project_id wt_public_id not null,
store_id wt_public_id not null
constraint credential_vault_store_fkey
references credential_vault_store (public_id)
on delete cascade
on update cascade,
name wt_name,
description wt_description,
create_time wt_timestamp,
update_time wt_timestamp,
version wt_version,
vault_path text not null
constraint vault_path_must_not_be_empty
check(length(trim(vault_path)) > 0)
constraint vault_path_must_have_staticcred_or_creds
check(vault_path ~ '^.+\/(static-cred|creds)\/(?:[^\/\\\s]+\/)*[^\/\\\s]+$'),
credential_type text not null
constraint credential_type_enm_fkey
references credential_type_enm (name)
on delete restrict
on update cascade,
constraint credential_vault_ldap_library_store_id_public_id_uq
unique(store_id, public_id),
constraint credential_vault_ldap_library_store_id_name_uq
unique(store_id, name),
constraint credential_vault_library_fkey
foreign key (project_id, store_id, public_id, credential_type)
references credential_vault_library (project_id, store_id, public_id, credential_type)
on delete cascade
on update cascade
);
comment on table credential_vault_ldap_library is
'credential_vault_ldap_library is a credential library that issues credentials from a vault ldap secret backend.';
create trigger insert_credential_vault_library_subtype before insert on credential_vault_ldap_library
for each row execute procedure insert_credential_vault_library_subtype();
create trigger update_credential_vault_library_table_update_time before update on credential_vault_ldap_library
for each row execute procedure update_credential_vault_library_table_update_time();
create trigger immutable_columns before update on credential_vault_ldap_library
for each row execute procedure immutable_columns('public_id', 'store_id', 'project_id', 'credential_type', 'create_time');
create trigger delete_credential_vault_library_subtype after delete on credential_vault_ldap_library
for each row execute procedure delete_credential_vault_library_subtype();
create trigger update_version_column after update on credential_vault_ldap_library
for each row execute procedure update_version_column();
create trigger update_time_column before update on credential_vault_ldap_library
for each row execute procedure update_time_column();
create trigger default_create_time_column before insert on credential_vault_ldap_library
for each row execute procedure default_create_time();
create trigger before_insert_credential_vault_library before insert on credential_vault_ldap_library
for each row execute procedure before_insert_credential_vault_library();
create function default_vault_ldap_credential_type() returns trigger
as $$
begin
if new.credential_type is distinct from 'username_password_domain' then
new.credential_type = 'username_password_domain';
end if;
return new;
end;
$$ language plpgsql;
comment on function default_vault_ldap_credential_type is
'default_vault_ldap_credential_type ensures the credential_type is set to username_password_domain';
create trigger default_vault_ldap_credential_type before insert on credential_vault_ldap_library
for each row execute procedure default_vault_ldap_credential_type();
-- Replaces view from 99/01_credential_vault_library_refactor.up.sql
drop view credential_vault_library_issue_credentials;
create view credential_vault_library_issue_credentials as
with
password_override (library_id, username_attribute, password_attribute) as (
select library_id,
nullif(username_attribute, wt_to_sentinel('no override')),
nullif(password_attribute, wt_to_sentinel('no override'))
from credential_vault_generic_library_username_password_mapping_ovrd
),
ssh_private_key_override (library_id, username_attribute, private_key_attribute, private_key_passphrase_attribute) as (
select library_id,
nullif(username_attribute, wt_to_sentinel('no override')),
nullif(private_key_attribute, wt_to_sentinel('no override')),
nullif(private_key_passphrase_attribute, wt_to_sentinel('no override'))
from credential_vault_generic_library_ssh_private_key_mapping_ovrd
),
password_domain_override (library_id, username_attribute, password_attribute, domain_attribute) as (
select library_id,
nullif(username_attribute, wt_to_sentinel('no override')),
nullif(password_attribute, wt_to_sentinel('no override')),
nullif(domain_attribute, wt_to_sentinel('no override'))
from credential_vault_generic_library_usern_pass_domain_mapping_ovrd
)
select library.public_id as public_id,
library.store_id as store_id,
library.name as name,
library.description as description,
library.create_time as create_time,
library.update_time as update_time,
library.version as version,
library.vault_path as vault_path,
library.http_method as http_method,
library.http_request_body as http_request_body,
library.credential_type as credential_type,
null as key_type,
null as key_bits,
null as username,
null as ttl,
null as key_id,
null as critical_options,
null as extensions,
store.project_id as project_id,
store.vault_address as vault_address,
store.namespace as namespace,
store.ca_cert as ca_cert,
store.tls_server_name as tls_server_name,
store.tls_skip_verify as tls_skip_verify,
store.worker_filter as worker_filter,
store.ct_token as ct_token, -- encrypted
store.token_hmac as token_hmac,
store.token_status as token_status,
store.token_key_id as token_key_id,
store.client_cert as client_cert,
store.ct_client_key as ct_client_key, -- encrypted
store.client_key_id as client_key_id,
coalesce(upasso.username_attribute, sshpk.username_attribute, pd.username_attribute)
as username_attribute,
coalesce(upasso.password_attribute, pd.password_attribute)
as password_attribute,
pd.domain_attribute as domain_attribute,
sshpk.private_key_attribute as private_key_attribute,
sshpk.private_key_passphrase_attribute as private_key_passphrase_attribute,
'generic' as cred_lib_type, -- used to switch on
null as additional_valid_principals
from credential_vault_generic_library library
join credential_vault_store_client store
on library.store_id = store.public_id
left join password_override upasso
on library.public_id = upasso.library_id
left join ssh_private_key_override sshpk
on library.public_id = sshpk.library_id
left join password_domain_override pd
on library.public_id = pd.library_id
union
select library.public_id as public_id,
library.store_id as store_id,
library.name as name,
library.description as description,
library.create_time as create_time,
library.update_time as update_time,
library.version as version,
library.vault_path as vault_path,
null as http_method,
null as http_request_body,
library.credential_type as credential_type,
library.key_type as key_type,
library.key_bits as key_bits,
library.username as username,
library.ttl as ttl,
library.key_id as key_id,
library.critical_options as critical_options,
library.extensions as extensions,
store.project_id as project_id,
store.vault_address as vault_address,
store.namespace as namespace,
store.ca_cert as ca_cert,
store.tls_server_name as tls_server_name,
store.tls_skip_verify as tls_skip_verify,
store.worker_filter as worker_filter,
store.ct_token as ct_token, -- encrypted
store.token_hmac as token_hmac,
store.token_status as token_status,
store.token_key_id as token_key_id,
store.client_cert as client_cert,
store.ct_client_key as ct_client_key, -- encrypted
store.client_key_id as client_key_id,
null as username_attribute,
null as password_attribute,
null as domain_attribute,
null as private_key_attribute,
null as private_key_passphrase_attribute,
'ssh-signed-cert' as cred_lib_type, -- used to switch on
additional_valid_principals as additional_valid_principals
from credential_vault_ssh_cert_library library
join credential_vault_store_client store
on library.store_id = store.public_id
union
select library.public_id as public_id,
library.store_id as store_id,
library.name as name,
library.description as description,
library.create_time as create_time,
library.update_time as update_time,
library.version as version,
library.vault_path as vault_path,
null as http_method,
null as http_request_body,
library.credential_type as credential_type,
null as key_type,
null as key_bits,
null as username,
null as ttl,
null as key_id,
null as critical_options,
null as extensions,
store.project_id as project_id,
store.vault_address as vault_address,
store.namespace as namespace,
store.ca_cert as ca_cert,
store.tls_server_name as tls_server_name,
store.tls_skip_verify as tls_skip_verify,
store.worker_filter as worker_filter,
store.ct_token as ct_token, -- encrypted
store.token_hmac as token_hmac,
store.token_status as token_status,
store.token_key_id as token_key_id,
store.client_cert as client_cert,
store.ct_client_key as ct_client_key, -- encrypted
store.client_key_id as client_key_id,
pd.username_attribute as username_attribute,
pd.password_attribute as password_attribute,
pd.domain_attribute as domain_attribute,
null as private_key_attribute,
null as private_key_passphrase_attribute,
'ldap' as cred_lib_type, -- used to switch on
null as additional_valid_principals
from credential_vault_ldap_library library
join credential_vault_store_client store
on library.store_id = store.public_id
left join password_domain_override pd
on library.public_id = pd.library_id;
comment on view credential_vault_library_issue_credentials is
'credential_vault_library_issue_credentials is a view where each row contains a credential library and the credential library''s data needed to connect to Vault. '
'This view should only be used when issuing credentials from a Vault credential library. Each row may contain encrypted data. '
'This view should not be used to retrieve data which will be returned external to boundary.';
insert into oplog_ticket (name, version)
values
('credential_vault_ldap_library', 1);
commit;
@@ -4,6 +4,7 @@
begin;
-- Replaces view from 56/02_add_data_key_foreign_key_references.up.sql
-- Replaced in 78/01_ssh_signed_certs_additional_valid_principals
drop view credential_vault_library_issue_credentials;
create view credential_vault_library_issue_credentials as
with
@@ -378,6 +378,7 @@ begin;
from final;
-- Replaces view defined in 98/02_username_password_domain_vault.up.sql
-- Replaced in 100/01_credential_vault_ldap_library.up.sql
drop view credential_vault_library_issue_credentials;
create view credential_vault_library_issue_credentials as
with
@@ -493,6 +493,13 @@ begin;
('cvs__rcolors', 'cvl__ssh__r1', 'red vault ssh library', '/ssh/issue/red', 'webdev', 'ecdsa', 521),
('cvs__gcolors', 'cvl__ssh__g1', 'green vault ssh library', '/ssh/issue/green', 'dba', 'rsa', 4096);
insert into credential_vault_ldap_library
(store_id, public_id, name, vault_path, credential_type)
values
('cvs__bcolors', 'cvl__ldap_b1', 'blue vault ldap library', '/ldap/static-cred/blue', 'username_password_domain'),
('cvs__rcolors', 'cvl__ldap_r1', 'red vault ldap library', '/ldap/creds/red', 'username_password_domain'),
('cvs__gcolors', 'cvl__ldap_g1', 'green vault ldap library', '/ldap/static-cred/org-colors-r-us/group-green-color/green','username_password_domain');
insert into credential_static_store
(project_id, public_id, name, description)
values
@@ -0,0 +1,64 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: BUSL-1.1
begin;
select plan(4);
select wtt_load('widgets', 'iam', 'kms', 'auth', 'hosts', 'targets', 'credentials');
select lives_ok(
$$
insert into credential_vault_ldap_library
(store_id, public_id, vault_path, credential_type)
values
('vs_______wvs', 'vl______vlsc1', '/ldap/static-cred/foo', 'username_password_domain'),
('vs_______wvs', 'vl______vlsc2', '/ldap/static-cred/foo/bar', 'username_password_domain'),
('vs_______wvs', 'vl______vlsc3', '/ldap/static-cred/foo/bar/baz', 'username_password_domain'),
('vs_______wvs', 'vl______vlsc4', '/ldap/static-cred/foo/bar/baz/more/paths', 'username_password_domain'),
('vs_______wvs', 'vl______vldyn5', '/ldap/creds/foo', 'username_password_domain'),
('vs_______wvs', 'vl______vldyn6', '/ldap/creds/foo/bar/baz/more/paths', 'username_password_domain'),
('vs_______wvs', 'vl______vldyn7', '/ldap/creds/foo/bar/baz', 'something_that_doesnt_exist');
$$
);
select results_eq(
$$
select public_id, project_id, store_id, name, description, vault_path, credential_type
from credential_vault_ldap_library
where public_id like 'vl______vlsc%'
or public_id like 'vl______vldyn%'
order by public_id;
$$,
$$
values
('vl______vldyn5'::wt_public_id, 'p____bwidget'::wt_public_id, 'vs_______wvs'::wt_public_id, null::wt_name, null::wt_description, '/ldap/creds/foo', 'username_password_domain'),
('vl______vldyn6'::wt_public_id, 'p____bwidget'::wt_public_id, 'vs_______wvs'::wt_public_id, null::wt_name, null::wt_description, '/ldap/creds/foo/bar/baz/more/paths', 'username_password_domain'),
('vl______vldyn7'::wt_public_id, 'p____bwidget'::wt_public_id, 'vs_______wvs'::wt_public_id, null::wt_name, null::wt_description, '/ldap/creds/foo/bar/baz', 'username_password_domain'),
('vl______vlsc1'::wt_public_id, 'p____bwidget'::wt_public_id, 'vs_______wvs'::wt_public_id, null::wt_name, null::wt_description, '/ldap/static-cred/foo', 'username_password_domain'),
('vl______vlsc2'::wt_public_id, 'p____bwidget'::wt_public_id, 'vs_______wvs'::wt_public_id, null::wt_name, null::wt_description, '/ldap/static-cred/foo/bar', 'username_password_domain'),
('vl______vlsc3'::wt_public_id, 'p____bwidget'::wt_public_id, 'vs_______wvs'::wt_public_id, null::wt_name, null::wt_description, '/ldap/static-cred/foo/bar/baz', 'username_password_domain'),
('vl______vlsc4'::wt_public_id, 'p____bwidget'::wt_public_id, 'vs_______wvs'::wt_public_id, null::wt_name, null::wt_description, '/ldap/static-cred/foo/bar/baz/more/paths', 'username_password_domain');
$$
);
select row_eq(
$$
select count(*)
from credential_vault_library
where public_id like 'vl______vlsc%'
or public_id like 'vl______vldyn%';
$$,
row(7::bigint)
);
select row_eq(
$$
select count(*)
from credential_library
where public_id like 'vl______vlsc%'
or public_id like 'vl______vldyn%';
$$,
row(7::bigint)
);
select * from finish();
rollback;
@@ -555,14 +555,17 @@ begin;
$$,
$$
values
( 'cvl_______b1'::wt_public_id, 'blue vault library'::wt_name),
( 'cvl__ssh__b1'::wt_public_id, 'blue vault ssh library'::wt_name),
( 'cvl_______g1'::wt_public_id, 'green vault library'::wt_name),
( 'cvl__ssh__g1'::wt_public_id, 'green vault ssh library'::wt_name),
( 'cvl_______r1'::wt_public_id, 'red vault library'::wt_name),
( 'cvl__ssh__r1'::wt_public_id, 'red vault ssh library'::wt_name),
( 'clvlt_V134iOjA'::wt_public_id, 'vault_generic1_updated'::wt_name),
('clvsclt_35iWGH12'::wt_public_id, 'vault_ssh_cert1'::wt_name)
( 'cvl__ldap_b1'::wt_public_id, 'blue vault ldap library'::wt_name),
( 'cvl_______b1'::wt_public_id, 'blue vault library'::wt_name),
( 'cvl__ssh__b1'::wt_public_id, 'blue vault ssh library'::wt_name),
( 'cvl__ldap_g1'::wt_public_id, 'green vault ldap library'::wt_name),
( 'cvl_______g1'::wt_public_id, 'green vault library'::wt_name),
( 'cvl__ssh__g1'::wt_public_id, 'green vault ssh library'::wt_name),
( 'cvl__ldap_r1'::wt_public_id, 'red vault ldap library'::wt_name),
( 'cvl_______r1'::wt_public_id, 'red vault library'::wt_name),
( 'cvl__ssh__r1'::wt_public_id, 'red vault ssh library'::wt_name),
( 'clvlt_V134iOjA'::wt_public_id, 'vault_generic1_updated'::wt_name),
('clvsclt_35iWGH12'::wt_public_id, 'vault_ssh_cert1'::wt_name);
$$
);
@@ -578,7 +581,7 @@ begin;
( 'cvl_______b1'::wt_public_id, 'blue vault library'::wt_name),
( 'cvl_______g1'::wt_public_id, 'green vault library'::wt_name),
( 'cvl_______r1'::wt_public_id, 'red vault library'::wt_name),
( 'clvlt_V134iOjA'::wt_public_id, 'vault_generic1_updated'::wt_name)
( 'clvlt_V134iOjA'::wt_public_id, 'vault_generic1_updated'::wt_name);
$$
);