mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-22 19:29:13 +08:00
feat(ql3): persist package secret approval plans
This commit is contained in:
@@ -63,6 +63,7 @@ import { pg0057RunManagementStopBoundaryMigration } from '../run-management/pg-0
|
||||
import { pg0058PluginPackageAutomationDispositionEventsMigration } from './pg-0058-plugin-package-automation-disposition-events';
|
||||
import { pg0059PluginPackageSecretBindingsMigration } from './pg-0059-plugin-package-secret-bindings';
|
||||
import { pg0060PluginPackageSecretMaterializationGuardMigration } from './pg-0060-plugin-package-secret-materialization-guard';
|
||||
import { pg0061PluginPackageSecretBindingApprovalPlansMigration } from './pg-0061-plugin-package-secret-binding-approval-plans';
|
||||
|
||||
export const postgresqlMainMigrationStream: MigrationStreamDefinition<PostgresMigrationContext> =
|
||||
Object.freeze({
|
||||
@@ -131,5 +132,6 @@ export const postgresqlMainMigrationStream: MigrationStreamDefinition<PostgresMi
|
||||
pg0058PluginPackageAutomationDispositionEventsMigration,
|
||||
pg0059PluginPackageSecretBindingsMigration,
|
||||
pg0060PluginPackageSecretMaterializationGuardMigration,
|
||||
pg0061PluginPackageSecretBindingApprovalPlansMigration,
|
||||
]),
|
||||
});
|
||||
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
import { CAPABILITIES_V59 } from './pg-0060-plugin-package-secret-materialization-guard';
|
||||
import { definePostgresSqlMigration } from './sqlMigration';
|
||||
|
||||
export const CAPABILITIES_V60 = CAPABILITIES_V59.replace(
|
||||
'"plugin_package_secret_binding":1,',
|
||||
'"plugin_package_secret_binding":1,"plugin_package_secret_binding_approval_plan":1,',
|
||||
);
|
||||
|
||||
export const pg0061PluginPackageSecretBindingApprovalPlansMigration =
|
||||
definePostgresSqlMigration({
|
||||
id: 'pg-0061-plugin-package-secret-binding-approval-plans',
|
||||
statements: [
|
||||
`
|
||||
CREATE TABLE "ql3"."plugin_package_secret_binding_approval_plans" (
|
||||
action_ref varchar(255) PRIMARY KEY,
|
||||
approval_plan_digest char(64) NOT NULL,
|
||||
binding_plan_digest char(64) NOT NULL,
|
||||
generation_digest char(64) NOT NULL,
|
||||
project_id varchar(128) NOT NULL,
|
||||
package_name varchar(63) NOT NULL,
|
||||
installation_id varchar(128) NOT NULL,
|
||||
lock_digest char(64) NOT NULL,
|
||||
generation integer NOT NULL,
|
||||
manifest_digest char(64) NOT NULL,
|
||||
requested_by_type varchar(16) NOT NULL,
|
||||
requested_by_id varchar(255) NOT NULL,
|
||||
planned_at_ms bigint NOT NULL,
|
||||
expires_at_ms bigint NOT NULL,
|
||||
plan_json jsonb NOT NULL,
|
||||
CONSTRAINT ql3_plugin_package_secret_binding_approval_plan_project_fk
|
||||
FOREIGN KEY (project_id) REFERENCES "ql3"."projects" (id)
|
||||
ON DELETE RESTRICT ON UPDATE RESTRICT,
|
||||
CONSTRAINT ql3_plugin_package_secret_binding_approval_plan_install_fk
|
||||
FOREIGN KEY (installation_id)
|
||||
REFERENCES "ql3"."plugin_package_installs" (installation_id)
|
||||
ON DELETE RESTRICT ON UPDATE RESTRICT,
|
||||
CONSTRAINT ql3_plugin_package_secret_binding_approval_plan_identity_check CHECK (
|
||||
action_ref ~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$' AND
|
||||
project_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
|
||||
package_name ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' AND
|
||||
installation_id ~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' AND
|
||||
generation BETWEEN 1 AND 2147483647 AND
|
||||
requested_by_type = 'user' AND
|
||||
octet_length(requested_by_id) BETWEEN 1 AND 255 AND
|
||||
requested_by_id !~ '[[:cntrl:]]'
|
||||
),
|
||||
CONSTRAINT ql3_plugin_package_secret_binding_approval_plan_digest_check CHECK (
|
||||
approval_plan_digest ~ '^[0-9a-f]{64}$' AND
|
||||
binding_plan_digest ~ '^[0-9a-f]{64}$' AND
|
||||
generation_digest ~ '^[0-9a-f]{64}$' AND
|
||||
lock_digest ~ '^[0-9a-f]{64}$' AND
|
||||
manifest_digest ~ '^[0-9a-f]{64}$'
|
||||
),
|
||||
CONSTRAINT ql3_plugin_package_secret_binding_approval_plan_time_check CHECK (
|
||||
planned_at_ms >= 0 AND
|
||||
expires_at_ms > planned_at_ms AND
|
||||
expires_at_ms - planned_at_ms <= 900000
|
||||
),
|
||||
CONSTRAINT ql3_plugin_package_secret_binding_approval_plan_json_check CHECK (
|
||||
jsonb_typeof(plan_json) = 'object' AND
|
||||
octet_length(plan_json::text) BETWEEN 2 AND 98304 AND
|
||||
plan_json @> jsonb_build_object(
|
||||
'schema', 'qinglong/plugin-package-secret-binding-approval-plan@v1',
|
||||
'actionRef', action_ref,
|
||||
'approvalPlanDigest', approval_plan_digest,
|
||||
'requestedBy', jsonb_build_object(
|
||||
'type', requested_by_type,
|
||||
'id', requested_by_id
|
||||
),
|
||||
'expiresAtMs', expires_at_ms,
|
||||
'bindingPlan', jsonb_build_object(
|
||||
'schema', 'qinglong/plugin-package-secret-binding-plan@v1',
|
||||
'planDigest', binding_plan_digest,
|
||||
'plannedAtMs', planned_at_ms,
|
||||
'target', jsonb_build_object(
|
||||
'generationDigest', generation_digest,
|
||||
'projectId', project_id,
|
||||
'packageName', package_name,
|
||||
'installationId', installation_id,
|
||||
'lockDigest', lock_digest,
|
||||
'generation', generation,
|
||||
'manifestDigest', manifest_digest
|
||||
)
|
||||
)
|
||||
) AND
|
||||
jsonb_typeof(plan_json #> '{bindingPlan,entries}') = 'array' AND
|
||||
jsonb_array_length(plan_json #> '{bindingPlan,entries}') BETWEEN 1 AND 64
|
||||
)
|
||||
)
|
||||
`.trim(),
|
||||
`CREATE UNIQUE INDEX ql3_plugin_package_secret_binding_approval_plan_digest_uidx ON "ql3"."plugin_package_secret_binding_approval_plans" (approval_plan_digest)`,
|
||||
`CREATE INDEX ql3_plugin_package_secret_binding_approval_plan_target_idx ON "ql3"."plugin_package_secret_binding_approval_plans" (project_id, package_name, generation, action_ref)`,
|
||||
`CREATE INDEX ql3_plugin_package_secret_binding_approval_plan_expiry_idx ON "ql3"."plugin_package_secret_binding_approval_plans" (expires_at_ms, action_ref)`,
|
||||
`
|
||||
CREATE FUNCTION "ql3"."plugin_package_secret_binding_planning_snapshot"(
|
||||
p_project_id varchar,
|
||||
p_package_name varchar
|
||||
)
|
||||
RETURNS TABLE (
|
||||
record_json jsonb,
|
||||
lock_json jsonb,
|
||||
proposal_json jsonb,
|
||||
observed_at_ms bigint
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
VOLATILE
|
||||
SECURITY DEFINER
|
||||
SET search_path = pg_catalog, ql3
|
||||
AS $ql3$
|
||||
BEGIN
|
||||
IF NOT pg_has_role(session_user, 'ql3_package_manager', 'member') THEN
|
||||
RAISE EXCEPTION 'Package manager authority is required'
|
||||
USING ERRCODE = 'insufficient_privilege';
|
||||
END IF;
|
||||
IF p_project_id !~ '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$' OR
|
||||
p_package_name !~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' THEN
|
||||
RAISE EXCEPTION 'Package planning identity is invalid'
|
||||
USING ERRCODE = 'invalid_parameter_value';
|
||||
END IF;
|
||||
|
||||
RETURN QUERY
|
||||
SELECT install.record_json,
|
||||
install.lock_json,
|
||||
proposal.proposal_json,
|
||||
floor(extract(epoch FROM transaction_timestamp()) * 1000)::bigint
|
||||
FROM "ql3"."plugin_package_install_heads" AS head
|
||||
JOIN "ql3"."plugin_package_installs" AS install
|
||||
ON install.installation_id = head.installation_id
|
||||
JOIN "ql3"."plugin_package_admission_receipts" AS admission
|
||||
ON admission.installation_id = install.installation_id
|
||||
JOIN "ql3"."plugin_package_install_proposals" AS proposal
|
||||
ON proposal.action_ref = admission.action_ref
|
||||
LEFT JOIN "ql3"."plugin_package_quarantine_events" AS quarantine
|
||||
ON quarantine.project_id = install.project_id
|
||||
AND quarantine.package_name = install.package_name
|
||||
AND quarantine.installation_id = install.installation_id
|
||||
AND quarantine.lock_digest = install.lock_digest
|
||||
LEFT JOIN "ql3"."plugin_package_lifecycle_heads" AS lifecycle
|
||||
ON lifecycle.project_id = install.project_id
|
||||
AND lifecycle.package_name = install.package_name
|
||||
AND lifecycle.installation_id = install.installation_id
|
||||
AND lifecycle.lock_digest = install.lock_digest
|
||||
WHERE head.project_id = p_project_id
|
||||
AND head.package_name = p_package_name
|
||||
AND install.state = 'active'
|
||||
AND install.active_lock_digest = install.lock_digest
|
||||
AND quarantine.event_digest IS NULL
|
||||
AND COALESCE(lifecycle.disposition, 'active') = 'active'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "ql3"."plugin_package_secret_bindings" AS binding
|
||||
WHERE binding.project_id = install.project_id
|
||||
AND binding.package_name = install.package_name
|
||||
AND binding.generation = install.target_generation
|
||||
)
|
||||
FOR SHARE OF head, install;
|
||||
END
|
||||
$ql3$
|
||||
`.trim(),
|
||||
`
|
||||
CREATE FUNCTION "ql3"."create_plugin_package_secret_binding_approval_plan"(
|
||||
p_plan_json jsonb
|
||||
)
|
||||
RETURNS varchar
|
||||
LANGUAGE plpgsql
|
||||
VOLATILE
|
||||
SECURITY DEFINER
|
||||
SET search_path = pg_catalog, ql3
|
||||
AS $ql3$
|
||||
DECLARE
|
||||
existing_plan jsonb;
|
||||
inserted_action_ref varchar(255);
|
||||
BEGIN
|
||||
IF NOT pg_has_role(session_user, 'ql3_package_manager', 'member') THEN
|
||||
RAISE EXCEPTION 'Package manager authority is required'
|
||||
USING ERRCODE = 'insufficient_privilege';
|
||||
END IF;
|
||||
IF jsonb_typeof(p_plan_json) IS DISTINCT FROM 'object' THEN
|
||||
RAISE EXCEPTION 'Secret binding approval plan is invalid'
|
||||
USING ERRCODE = 'invalid_parameter_value';
|
||||
END IF;
|
||||
IF COALESCE(p_plan_json ->> 'actionRef', '') !~
|
||||
'^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$' THEN
|
||||
RAISE EXCEPTION 'Secret binding approval actionRef is invalid'
|
||||
USING ERRCODE = 'invalid_parameter_value';
|
||||
END IF;
|
||||
|
||||
PERFORM pg_advisory_xact_lock(
|
||||
hashtextextended(p_plan_json ->> 'actionRef', 70513061)
|
||||
);
|
||||
|
||||
SELECT plan_json INTO existing_plan
|
||||
FROM "ql3"."plugin_package_secret_binding_approval_plans"
|
||||
WHERE action_ref = p_plan_json ->> 'actionRef'
|
||||
FOR SHARE;
|
||||
IF existing_plan IS NOT NULL THEN
|
||||
IF existing_plan = p_plan_json THEN
|
||||
RETURN 'existing';
|
||||
END IF;
|
||||
RAISE EXCEPTION 'Secret binding approval actionRef is already bound'
|
||||
USING ERRCODE = 'unique_violation';
|
||||
END IF;
|
||||
|
||||
INSERT INTO "ql3"."plugin_package_secret_binding_approval_plans" (
|
||||
action_ref, approval_plan_digest, binding_plan_digest,
|
||||
generation_digest, project_id, package_name, installation_id,
|
||||
lock_digest, generation, manifest_digest, requested_by_type,
|
||||
requested_by_id, planned_at_ms, expires_at_ms, plan_json
|
||||
)
|
||||
SELECT
|
||||
p_plan_json ->> 'actionRef',
|
||||
p_plan_json ->> 'approvalPlanDigest',
|
||||
p_plan_json #>> '{bindingPlan,planDigest}',
|
||||
p_plan_json #>> '{bindingPlan,target,generationDigest}',
|
||||
p_plan_json #>> '{bindingPlan,target,projectId}',
|
||||
p_plan_json #>> '{bindingPlan,target,packageName}',
|
||||
p_plan_json #>> '{bindingPlan,target,installationId}',
|
||||
p_plan_json #>> '{bindingPlan,target,lockDigest}',
|
||||
(p_plan_json #>> '{bindingPlan,target,generation}')::integer,
|
||||
p_plan_json #>> '{bindingPlan,target,manifestDigest}',
|
||||
p_plan_json #>> '{requestedBy,type}',
|
||||
p_plan_json #>> '{requestedBy,id}',
|
||||
(p_plan_json #>> '{bindingPlan,plannedAtMs}')::bigint,
|
||||
(p_plan_json ->> 'expiresAtMs')::bigint,
|
||||
p_plan_json
|
||||
FROM "ql3"."plugin_package_install_heads" AS head
|
||||
JOIN "ql3"."plugin_package_installs" AS install
|
||||
ON install.installation_id = head.installation_id
|
||||
AND install.project_id = head.project_id
|
||||
AND install.package_name = head.package_name
|
||||
LEFT JOIN "ql3"."plugin_package_quarantine_events" AS quarantine
|
||||
ON quarantine.project_id = install.project_id
|
||||
AND quarantine.package_name = install.package_name
|
||||
AND quarantine.installation_id = install.installation_id
|
||||
AND quarantine.lock_digest = install.lock_digest
|
||||
LEFT JOIN "ql3"."plugin_package_lifecycle_heads" AS lifecycle
|
||||
ON lifecycle.project_id = install.project_id
|
||||
AND lifecycle.package_name = install.package_name
|
||||
AND lifecycle.installation_id = install.installation_id
|
||||
AND lifecycle.lock_digest = install.lock_digest
|
||||
WHERE head.project_id = p_plan_json #>> '{bindingPlan,target,projectId}'
|
||||
AND head.package_name = p_plan_json #>> '{bindingPlan,target,packageName}'
|
||||
AND install.installation_id =
|
||||
p_plan_json #>> '{bindingPlan,target,installationId}'
|
||||
AND install.lock_digest =
|
||||
p_plan_json #>> '{bindingPlan,target,lockDigest}'
|
||||
AND install.target_generation =
|
||||
(p_plan_json #>> '{bindingPlan,target,generation}')::integer
|
||||
AND install.lock_json ->> 'manifestDigest' =
|
||||
p_plan_json #>> '{bindingPlan,target,manifestDigest}'
|
||||
AND install.state = 'active'
|
||||
AND install.active_lock_digest = install.lock_digest
|
||||
AND quarantine.event_digest IS NULL
|
||||
AND COALESCE(lifecycle.disposition, 'active') = 'active'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "ql3"."plugin_package_secret_bindings" AS binding
|
||||
WHERE binding.generation_digest =
|
||||
p_plan_json #>> '{bindingPlan,target,generationDigest}'
|
||||
OR (
|
||||
binding.project_id = install.project_id AND
|
||||
binding.package_name = install.package_name AND
|
||||
binding.generation = install.target_generation
|
||||
)
|
||||
)
|
||||
RETURNING action_ref INTO inserted_action_ref;
|
||||
|
||||
IF inserted_action_ref IS NULL THEN
|
||||
RAISE EXCEPTION 'Secret binding target is not the current unbound generation'
|
||||
USING ERRCODE = 'check_violation';
|
||||
END IF;
|
||||
RETURN 'created';
|
||||
END
|
||||
$ql3$
|
||||
`.trim(),
|
||||
`REVOKE ALL ON "ql3"."plugin_package_secret_binding_approval_plans" FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager, ql3_package_executor, ql3_worker_ingress`,
|
||||
`GRANT SELECT ON "ql3"."plugin_package_secret_binding_approval_plans" TO ql3_package_manager`,
|
||||
`GRANT SELECT ON "ql3"."plugin_package_secret_binding_approval_plans" TO ql3_package_executor`,
|
||||
`REVOKE ALL ON FUNCTION "ql3"."plugin_package_secret_binding_planning_snapshot"(varchar, varchar) FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager, ql3_package_executor, ql3_worker_ingress`,
|
||||
`REVOKE ALL ON FUNCTION "ql3"."create_plugin_package_secret_binding_approval_plan"(jsonb) FROM PUBLIC, ql3_runtime, ql3_admin, ql3_package_manager, ql3_package_executor, ql3_worker_ingress`,
|
||||
`GRANT EXECUTE ON FUNCTION "ql3"."plugin_package_secret_binding_planning_snapshot"(varchar, varchar) TO ql3_package_manager`,
|
||||
`GRANT EXECUTE ON FUNCTION "ql3"."create_plugin_package_secret_binding_approval_plan"(jsonb) TO ql3_package_manager`,
|
||||
`DO $ql3$ BEGIN UPDATE "ql3"."schema_capabilities" SET contract_version = 60, migration_id = 'pg-0061-plugin-package-secret-binding-approval-plans', capabilities = '${CAPABILITIES_V60}'::jsonb, updated_at_ms = floor(extract(epoch FROM transaction_timestamp()) * 1000)::bigint WHERE contract_name = 'control-core' AND contract_version = 59 AND migration_id = 'pg-0060-plugin-package-secret-materialization-guard' AND capabilities = '${CAPABILITIES_V59}'::jsonb; IF NOT FOUND THEN RAISE EXCEPTION 'control-core capability is not at version 59' USING ERRCODE = 'check_violation'; END IF; END $ql3$`,
|
||||
],
|
||||
});
|
||||
Reference in New Issue
Block a user