Rebuilds the qbit on QQQ 4.1.0-RC.4 per the assessment (QRun-IO/qqq#1105, decisions D1-D8): - webhooks_endpoint, webhooks_endpoint_secret, webhooks_subscription, webhooks_delivery and webhooks_delivery_attempt (snake_case, webhooks_ prefix), permissions webhooks.view / manage / admin - Standard Webhooks signing with per-endpoint secrets (AES-GCM or env references) and overlapping rotation - SSRF-safe client: private, loopback, link-local and metadata ranges blocked, DNS pinned, no redirects, timeouts, size cap, admin-only internal allowlist (shared/ is an internal copy of QRun-IO/qqq#1109, replaced at RC.5) - event sources: table insert/update/delete (record change listener), process completed/failed, ESB topics (own events skipped, CloudEvent id dedup), custom events and a channel API for other qbits - delivery: unique attempt-row claims with leases (no double sends across replicas), retries with backoff, Retry-After, dead letters and Replay, serial mode, per-endpoint rate limits, health with probation and auto-disable, alerts through the Alerts SPI when present, retention - subscriptions: record filters, record security, read permission check, detail levels, include and exclude fields, payload customizer hook - app home dashboard, actions with the standard review/result screens, ESB / Quick Search / API integration hooks - JaCoCo gate, Checkstyle in verify, Maven wrapper, default 4.1 profile, Postgres DDL in docs/ddl The 0.x sources stay in the tree, excluded from the build, until their removal is approved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
72 lines
2.6 KiB
Java
72 lines
2.6 KiB
Java
/*
|
|
* QQQ - Low-code Application Framework for Engineers.
|
|
* Copyright (C) 2021-2025. Kingsrook, LLC
|
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
|
* contact@kingsrook.com
|
|
* https://github.com/Kingsrook/
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* https://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.kingsrook.qbits.webhooks.secrets;
|
|
|
|
|
|
import com.kingsrook.qqq.backend.core.instances.QMetaDataVariableInterpreter;
|
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
|
|
|
|
|
/*******************************************************************************
|
|
** Looks up a secret by name: a JVM system property, then an environment
|
|
** variable, then QQQ's variable interpreter (which also reads a .env file).
|
|
** Kubernetes secrets from External Secrets or Infisical arrive as environment
|
|
** variables, so a reference is just the variable's name.
|
|
*******************************************************************************/
|
|
public final class EnvironmentSecrets
|
|
{
|
|
/** What a reference may look like: an environment variable name. */
|
|
public static final String NAME_PATTERN = "[A-Za-z_][A-Za-z0-9_]{0,99}";
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
** Utility class.
|
|
*******************************************************************************/
|
|
private EnvironmentSecrets()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
** The value, or null.
|
|
*******************************************************************************/
|
|
public static String lookup(String name)
|
|
{
|
|
if(!StringUtils.hasContent(name) || !name.matches(NAME_PATTERN))
|
|
{
|
|
return (null);
|
|
}
|
|
String value = System.getProperty(name);
|
|
if(!StringUtils.hasContent(value))
|
|
{
|
|
value = System.getenv(name);
|
|
}
|
|
if(!StringUtils.hasContent(value))
|
|
{
|
|
String interpreted = new QMetaDataVariableInterpreter().interpret("${env." + name + "}");
|
|
value = interpreted == null || interpreted.startsWith("${") ? null : interpreted;
|
|
}
|
|
return (StringUtils.hasContent(value) ? value : null);
|
|
}
|
|
}
|