diff --git a/.github/workflows/publish-current-server.yml b/.github/workflows/publish-current-server.yml index a19b728639..748e253bfa 100644 --- a/.github/workflows/publish-current-server.yml +++ b/.github/workflows/publish-current-server.yml @@ -73,6 +73,7 @@ jobs: python3 source/scripts/test-publisher-safety-guards.py python3 source/scripts/test-web-console-sbom.py python3 source/scripts/test-server-backport-consumer-contract.py + python3 source/scripts/test-ai-resource-api-guards.py declared_release="$(sed -n 's/^ARG SERVER_RELEASE_TAG=//p' \ source/server/Dockerfile.web-compose-release | sort -u)" @@ -280,11 +281,17 @@ jobs: # Only arm cleanup after proving all names are available. A collision # must never remove another run's container or persistent volumes. trap cleanup_candidate EXIT + # Exercise the opt-in protocol on this disposable runtime while + # retaining the image's required Java arguments. Image defaults and + # the published configuration remain unchanged. + candidate_java_opts="$(docker image inspect "$CANDIDATE_IMAGE" \ + --format '{{range .Config.Env}}{{println .}}{{end}}' | sed -n 's/^JAVA_OPTS=//p')" docker run -d \ --name "$CANDIDATE_NAME" \ --restart no \ -p 127.0.0.1:18082:8080 \ -e PROXY_PLATFORM_PUBLIC_ORIGIN=https://stack.example.test \ + -e "JAVA_OPTS=${candidate_java_opts} -Dapi.ai.bridge.enabled=true -Dapi.ai.service.upgrade.enabled=true -Dapi.ai.resource.change.enabled=true" \ -v "$CATTLE_VOLUME:/var/lib/cattle" \ -v "$MYSQL_VOLUME:/var/lib/mysql" \ -v "$MYSQL_LOG_VOLUME:/var/log/mysql" \ @@ -422,8 +429,10 @@ jobs: # Exercise the published API and real auth overlay on this fresh, # disposable database before the image is allowed to be released. python3 source/scripts/test-mfa-policy-api.py \ - --port 18082 --disposable --registration-basic | + --port 18082 --disposable --registration-basic --ai-resource | tee "$evidence/mfa-policy-api-smoke.txt" + grep -E '^AI_RESOURCE_API_OK checks=[0-9]+ scoped_create_read=true process_pool=true human_cookie=true no_hosts=true$' \ + "$evidence/mfa-policy-api-smoke.txt" >/dev/null grep -E '^REGISTRATION_BASIC_API_OK checks=7 ordinary_user=true entry_only=true node_active_verified=false script_sha256=[0-9a-f]{64}$' \ "$evidence/mfa-policy-api-smoke.txt" >"$evidence/registration-basic-api-smoke.txt" diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index 5ad7d83590..50f314d0ee 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -1,5 +1,16 @@ # Compatibility Contract +## Server v1.6.557 source candidate + +This candidate retains Web Console 1.6.199 and bridge 0.2.1 and consumes the +qualified Engine 0.183.357 artifact. It repairs decoded internal Key scope reads +and native process-pool identities. Public typed IDs, live actor ceilings, +child DENY and ordinary Full access are preserved. See the +[candidate note](docs/releases/server-1.6.557.md) for exact component inputs, +unfinished QA and rollback. It is not yet a published or accepted deployment; +the installation examples below remain on the published 556 image. + + ## Server v1.6.556 published diff --git a/docs/releases/server-1.6.557.md b/docs/releases/server-1.6.557.md new file mode 100644 index 0000000000..c13aa38668 --- /dev/null +++ b/docs/releases/server-1.6.557.md @@ -0,0 +1,54 @@ +# Server v1.6.557 candidate + +Not published. Install examples continue to use the current published 556 image +until the immutable 557 publication is verified. Deployment acceptance is pending. + +## Verified component inputs + +- Engine `v0.183.357`, original CI producer `2cd688b0c066658c41e7d3de5bed8c543687f275`, + merged tag source `6a5230ee2c2e6d4c4aa495035b8de30bb5d64d18`, JAR SHA256 `a46e832314b32292e3423133168020acf93052a7dd29e967bbaabc3df6dca8dc`. + Required CodeQL and Security run 40926481583 passed: 373 suites, 3,616 tests, + zero failures/errors and one existing platform-conditional skip. +- Web Console `1.6.199`, producer `80a47df65f6406087b80aa81cfa99fe1f438ecff`, + archive SHA256 `ab60d4baa10685021b74db09b805dee1f866e9bd0fbccea4d54610df907c7570`. +- Optional stdio bridge `0.2.1`, ZIP SHA256 + `f1477b74da0caefd7fcef77609b55b7d172683bda4afe3ffb884dfdf5a63dfae`. + Other bundled component pins and live ordinary UI/API paths are unchanged. + +## Corrected behavior + +Normal validation already decodes resource IDs before internal Key authorization. +The parent resolver now preserves those decoded identities instead of parsing +them a second time. A human-approved create and its original custom-Key receipt +can use the same live scope. Public scope inputs still require exact typed IDs; +foreign IDs, owner ceilings, child DENY and live revision checks remain enforced. + +The native process-pool owner supplies a read-only stable bean identity without +changing native display names, null IDs or metrics. AI metadata uses an opaque +identity and a safe fallback display name. Unnamed or duplicate-name pools no +longer break the whole list. The unsupported activeSetting collection is removed +from AI discovery; ordinary settings routes and permissions are unchanged. + +The publisher additionally exercises a real scoped-Key preview, human-cookie +confirmation, one empty Stack create and receipt read against its fresh disposable +Server. It checks native pool projection and unsupported-input errors without +Hosts or workloads. This protocol gate does not replace browser acceptance. +No production origin, runtime patch, authentication policy or firewall is changed. + +## Acceptance boundary and rollback + +Previously unaffected metadata, role and 16 new-modal layout results are retained. +The unfinished 18-pair workflow, remaining read adapters, paired child-DENY control +and weak-model use must be accepted on the designated 8080 installation. This +candidate does not complete every frontend WebMCP workflow. Catalog launch, +advanced forms, other business batches and KVM HOLD remain separately tracked. + +Back up the database, preserve named volumes and genuine operator overrides, +and retain the previous image. Keep the three existing opt-in AI properties +and all security, origin and performance settings. No new migration is added. +Before rollback, stop new clients, settle accepted work, cancel unused plans and +revoke temporary Keys. Preserve durable plan receipts and do not replay uncertain +operations. Follow the [Key-policy rollback guide](../upgrades/api-key-policy-rollback.md). +Officially unfixed Medium findings retain their exact package tracking policy; +the release scan must still reject applicable fixed, High/Critical or untracked +findings. Browser SBOM coverage remains explicitly incomplete. diff --git a/scripts/check-server-api-explorer-patch.sh b/scripts/check-server-api-explorer-patch.sh index 8729c85ab8..94c8c1e931 100755 --- a/scripts/check-server-api-explorer-patch.sh +++ b/scripts/check-server-api-explorer-patch.sh @@ -571,7 +571,7 @@ python3 scripts/test-web-console-sbom.py python3 server/security/test_web_console_sbom_scan.py require_marker "$release_dockerfile" \ - 'ARG SERVER_RELEASE_TAG=v1.6.556' \ + 'ARG SERVER_RELEASE_TAG=v1.6.557' \ SERVER_INCREMENTAL_RELEASE_DEFAULT_MISSING require_marker "$release_dockerfile" \ 'org.opencontainers.image.version="${SERVER_RELEASE_TAG}"' \ @@ -1139,21 +1139,21 @@ require_marker "$build_script" \ '--file server/Dockerfile.web-compose-release' \ SERVER_INCREMENTAL_RELEASE_BUILD_PATH_MISSING require_marker "$build_script" \ - 'image=${IMAGE:-pasturestack-validation/server:v1.6.556}' \ + 'image=${IMAGE:-pasturestack-validation/server:v1.6.557}' \ SERVER_INCREMENTAL_RELEASE_BUILD_VERSION_MISSING require_marker "$build_script" \ - 'server_release_tag=${SERVER_RELEASE_TAG:-v1.6.556}' \ + 'server_release_tag=${SERVER_RELEASE_TAG:-v1.6.557}' \ SERVER_INCREMENTAL_RELEASE_BUILD_DEFAULT_MISSING require_marker "$build_script" \ 'CATTLE_RANCHER_SERVER_VERSION="${server_release_tag}"' \ SERVER_INCREMENTAL_RELEASE_BUILD_RUNTIME_VERSION_MISSING for release_engine_marker in \ - 'ARG ORCHESTRATION_ENGINE_RELEASE_TAG=v0.183.356' \ + 'ARG ORCHESTRATION_ENGINE_RELEASE_TAG=v0.183.357' \ 'ARG ORCHESTRATION_ENGINE_ARTIFACT=cattle.jar' \ - 'ARG ORCHESTRATION_ENGINE_ARTIFACT_SHA256=dfce4c6df625a905a837770780bd09d871752cf9d8493b590145f84a8c78dd09' \ - 'ARG ORCHESTRATION_ENGINE_COMMIT=24cfa1db113f54de3148cd4ac3191e66a1702806' \ + 'ARG ORCHESTRATION_ENGINE_ARTIFACT_SHA256=a46e832314b32292e3423133168020acf93052a7dd29e967bbaabc3df6dca8dc' \ + 'ARG ORCHESTRATION_ENGINE_COMMIT=2cd688b0c066658c41e7d3de5bed8c543687f275' \ 'COPY --from=release_artifacts /out/orchestration-engine.jar /tmp/orchestration-engine.jar' \ - 'ARG ORCHESTRATION_ENGINE_VERSION=0.183.356' \ + 'ARG ORCHESTRATION_ENGINE_VERSION=0.183.357' \ 'sh /usr/share/cattle/verify-engine-archive.sh "${archive}" "${ORCHESTRATION_ENGINE_VERSION}" "${ORCHESTRATION_ENGINE_ARTIFACT_SHA256}"' \ 'cattle-resources-${ORCHESTRATION_ENGINE_VERSION}.jar' \ 'cattle-app-config-${ORCHESTRATION_ENGINE_VERSION}.jar' \ @@ -1172,10 +1172,10 @@ for release_engine_marker in \ SERVER_INCREMENTAL_ENGINE_REPLACEMENT_MISSING done for release_engine_build_marker in \ - 'orchestration_engine_release_tag=${ORCHESTRATION_ENGINE_RELEASE_TAG:-v0.183.356}' \ + 'orchestration_engine_release_tag=${ORCHESTRATION_ENGINE_RELEASE_TAG:-v0.183.357}' \ 'orchestration_engine_artifact=${ORCHESTRATION_ENGINE_ARTIFACT:-cattle.jar}' \ - 'orchestration_engine_artifact_sha256=${ORCHESTRATION_ENGINE_ARTIFACT_SHA256:-dfce4c6df625a905a837770780bd09d871752cf9d8493b590145f84a8c78dd09}' \ - 'orchestration_engine_commit=${ORCHESTRATION_ENGINE_COMMIT:-24cfa1db113f54de3148cd4ac3191e66a1702806}' \ + 'orchestration_engine_artifact_sha256=${ORCHESTRATION_ENGINE_ARTIFACT_SHA256:-a46e832314b32292e3423133168020acf93052a7dd29e967bbaabc3df6dca8dc}' \ + 'orchestration_engine_commit=${ORCHESTRATION_ENGINE_COMMIT:-2cd688b0c066658c41e7d3de5bed8c543687f275}' \ 'CATTLE_CATTLE_VERSION="${orchestration_engine_release_tag}"' \ 'cattle-resources-${ORCHESTRATION_ENGINE_VERSION}.jar' \ '< "${server_dir}/artifacts/verify-engine-archive.sh"'; do @@ -1694,10 +1694,10 @@ fi if grep -Fxq '## Current source candidate' README.md; then for candidate_readme_marker in \ '' \ - 'Server `v1.6.556` is a prepared source candidate, not a published image.' \ + 'Server `v1.6.557` is a prepared source candidate, not a published image.' \ 'run them only after its official release' \ 'This candidate is not yet available' \ - 'ghcr.io/pasturestack/server:v1.6.556'; do + 'ghcr.io/pasturestack/server:v1.6.557'; do require_marker README.md "$candidate_readme_marker" \ SERVER_CURRENT_CANDIDATE_README_MISSING done @@ -2303,7 +2303,7 @@ done jq -e ' ["CVE-2026-107928","CVE-2026-107929","CVE-2026-86409","CVE-2026-86410","CVE-2026-86412","CVE-2026-86414","CVE-2026-87862","CVE-2026-87863","CVE-2026-87864","CVE-2026-87865","CVE-2026-92386","CVE-2026-92387","CVE-2026-92388","CVE-2026-92389","CVE-2026-92390","CVE-2026-92391","CVE-2026-92392","CVE-2026-94266"] as $curl_fixed_cves | .["@context"] == "https://openvex.dev/ns/v0.2.0" - and .["@id"] == "https://github.com/PastureStack/server/security/openvex/v1.6.556" + and .["@id"] == "https://github.com/PastureStack/server/security/openvex/v1.6.557" and (.statements | length) == 56 and ([.statements[].vulnerability.name] | length == (unique | length)) and ([.statements[] | select(.status == "fixed") | .vulnerability.name] | sort) @@ -2341,7 +2341,7 @@ jq -r ' | @tsv ' "$runtime_vendor_pending" | LC_ALL=C sort -u >"$vendor_pending_fixture" bash "$vendor_pending_validator" "$runtime_vendor_pending" \ - "$vendor_pending_fixture" v1.6.556 >/dev/null + "$vendor_pending_fixture" v1.6.557 >/dev/null bash scripts/test-vendor-pending-findings.sh >/dev/null rm -f "$vendor_pending_fixture" trap - EXIT @@ -2430,4 +2430,4 @@ for release_readback_contract in \ fi done -printf 'SERVER_API_EXPLORER_PATCH_OK release=v1.6.556 base=v1.6.460 engine=0.183.356 web_console=1.6.199 catalog_service=0.20.15 webhook_automation_service=0.10.5 authentication_service=0.4.46 curl=8.18.0-1ubuntu2.8 freemarker=2.3.35 artifact_scan=required vendor_pending=exact-set role_matrix=qa-required locale_layout=qa-required\n' +printf 'SERVER_API_EXPLORER_PATCH_OK release=v1.6.557 base=v1.6.460 engine=0.183.357 web_console=1.6.199 catalog_service=0.20.15 webhook_automation_service=0.10.5 authentication_service=0.4.46 curl=8.18.0-1ubuntu2.8 freemarker=2.3.35 artifact_scan=required vendor_pending=exact-set role_matrix=qa-required locale_layout=qa-required\n' diff --git a/scripts/test-ai-resource-api-guards.py b/scripts/test-ai-resource-api-guards.py new file mode 100644 index 0000000000..697eca21a9 --- /dev/null +++ b/scripts/test-ai-resource-api-guards.py @@ -0,0 +1,29 @@ +"""Only guard regressions; actual protocol acceptance requires a real JVM.""" +import importlib.util +from pathlib import Path +import unittest +from unittest.mock import patch + +spec = importlib.util.spec_from_file_location('ai_smoke', Path(__file__).with_name('test-ai-resource-api.py')) +smoke = importlib.util.module_from_spec(spec) +spec.loader.exec_module(smoke) + + +class DisposableGuard(unittest.TestCase): + def test_missing_disposable_or_production_ports_fail_before_any_connection(self): + with patch.object(smoke.http.client, 'HTTPConnection', side_effect=AssertionError('Unexpected network request')) as connection: + for port, disposable in [(18082, False), (80, True), (443, True), (8080, True), (0, True), (65536, True)]: + with self.subTest(port=port, disposable=disposable), self.assertRaises(AssertionError): + smoke.run(port=port, administrator_jwt='guard-fixture', administrator_account_id='1a1', disposable=disposable) + connection.assert_not_called() + + def test_absent_administrator_session_fails_before_any_connection(self): + with patch.object(smoke.http.client, 'HTTPConnection', side_effect=AssertionError('Unexpected network request')) as connection: + for token, account in [(None, '1a1'), ('', '1a1'), ('guard-fixture', None)]: + with self.subTest(account=account), self.assertRaises(AssertionError): + smoke.run(port=18082, administrator_jwt=token, administrator_account_id=account, disposable=True) + connection.assert_not_called() + + +if __name__ == '__main__': + unittest.main() diff --git a/scripts/test-ai-resource-api.py b/scripts/test-ai-resource-api.py new file mode 100644 index 0000000000..f97a7a7757 --- /dev/null +++ b/scripts/test-ai-resource-api.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +"""Real typed-resource protocol smoke, only on a disposable loopback Server. + +Called from the existing fresh-install smoke with its in-memory administrator. +No Host, workload, volume, MFA weakening, external URL or secret output. +""" +import base64 +import http.client +import json +import secrets +import time +from urllib.parse import urlsplit + + +def run(*, port, administrator_jwt, administrator_account_id, disposable): + assert disposable and port not in (80, 443, 8080) and 1024 <= port <= 65535 + assert isinstance(administrator_jwt, str) and administrator_jwt and administrator_account_id + prefix = 'release-ai-' + secrets.token_hex(12) + stack = key = plan = None + public_origin = None + checks = [] + + def call(method, path, data=None, *, credential=None, human=False, expected=(200, 201, 202)): + assert method in ('GET', 'POST', 'DELETE') and path.startswith('/v2-beta/') + parsed = urlsplit(path) + assert not parsed.scheme and not parsed.netloc and not parsed.fragment + headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} + if credential: + headers['Authorization'] = 'Basic ' + base64.b64encode( + (credential['publicValue'] + ':' + credential['secretValue']).encode()).decode() + headers['X-PastureStack-Key-Expected-Revision'] = str(credential['apiKeyPolicyRevision']) + elif human: + assert public_origin + headers.update(Cookie='token=' + administrator_jwt, Origin=public_origin) + else: + headers['Authorization'] = 'Bearer ' + administrator_jwt + # The authority comes from this disposable Server's own canonical link; + # it is never followed as a network destination or supplied by a model. + if public_origin: + headers['Host'] = urlsplit(public_origin).netloc + connection = http.client.HTTPConnection('127.0.0.1', port, timeout=20) + try: + connection.request(method, path, body=None if data is None else json.dumps(data).encode(), headers=headers) + response = connection.getresponse(); raw = response.read(4 * 1024 * 1024 + 1) + assert len(raw) <= 4 * 1024 * 1024 + value = json.loads(raw) if raw else {} + assert response.status in expected, f'AI_RESOURCE_API_HTTP_{response.status}' + return value + finally: + connection.close() + + def check(name, value): + assert value, name + checks.append(name) + print('PASS ai-resource-' + name, flush=True) + + def settled(path, predicate, seconds=90): + deadline = time.monotonic() + seconds + while True: + value = call('GET', path) + if predicate(value): return value + assert time.monotonic() < deadline, 'AI_RESOURCE_API_SETTLEMENT_TIMEOUT' + time.sleep(.2) + + try: + projects = call('GET', '/v2-beta/projects?limit=100') + link = urlsplit(projects.get('links', {}).get('self', '')) + assert link.scheme in ('http', 'https') and link.netloc and not link.username and not link.password + public_origin = link.scheme + '://' + link.netloc + available = [row for row in projects.get('data', []) if row.get('state') == 'active'] + assert len(available) == 1, 'FRESH_DISPOSABLE_DEFAULT_PROJECT_REQUIRED' + project = available[0]; base = '/v2-beta/projects/' + project['id'] + pools = call('POST', base + '/aiResourceViews', {'resourceType': 'processPool'}) + rows = pools.get('data') + check('real-process-pool-owner-projection', isinstance(rows, list) and bool(rows) + and all(row.get('id', '').startswith('pool-') and row.get('name') for row in rows)) + detail = call('POST', base + '/aiResourceViews', {'resourceType': 'processPool', 'resourceId': rows[0]['id']}) + check('process-pool-opaque-detail', len(detail.get('data', [])) == 1 and detail['data'][0]['id'] == rows[0]['id']) + unsupported = call('POST', base + '/aiResourceViews', {'resourceType': 'activeSetting'}, expected=(422,)) + check('unsupported-native-collection-is-not-an-auth-denial', unsupported.get('code') == 'ResourceViewInputInvalid') + key = call('POST', '/v2-beta/apikeys', {'name': prefix + '-bridge', + 'apiKeyPolicy': {'purpose': 'ai-bridge', 'mode': 'custom', 'defaultEffect': 'deny', + 'rules': [{'id': 'one-disposable-project', 'effect': 'allow', + 'scope': {'kind': 'project', 'resourceId': project['id']}, + 'operations': ['read', 'create', 'update', 'delete']}]}}) + assert key.get('name') == prefix + '-bridge' and key.get('id') and key.get('uuid') + key_path = urlsplit(key['links']['self']).path + assert key_path.startswith(('/v2-beta/apikeys/', '/v2-beta/apikeyrestricteds/')) + fresh = settled(key_path, lambda row: row.get('state') == 'active', 30) + key['apiKeyPolicyRevision'] = fresh['apiKeyPolicyRevision'] + plan = call('POST', base + '/aiResourceChangePlans', {'resourceType': 'stack', 'operation': 'create', + 'parameters': {'name': prefix + '-stack', 'description': 'Disposable protocol smoke; no Hosts or workloads'}}, credential=key) + plan_path = base + '/aiResourceChangePlans/' + plan['id'] + check('scoped-key-preview-needs-human', plan.get('confirmationState') == 'pending') + denied = call('POST', plan_path + '?action=confirm', {}, credential=key, expected=(403,)) + check('key-cannot-confirm-itself', denied.get('code') in ('AiBridgeRouteDenied', 'AiKeyConfirmationForbidden')) + call('POST', plan_path + '?action=confirm', {}, human=True) + accepted = call('POST', plan_path + '?action=apply', {}, credential=key) + check('confirmed-create-accepted-once', accepted.get('status') == 'accepted') + deadline = time.monotonic() + 90 + while True: + result = call('GET', plan_path, credential=key) + if result.get('status') == 'succeeded': break + assert result.get('status') in ('accepted', 'running') and time.monotonic() < deadline, 'AI_RESOURCE_OPERATION_FAILED' + time.sleep(.2) + check('custom-key-can-read-decoded-created-target', result.get('verifiedResult') is True) + stack_id = result.get('resourceId'); assert stack_id + stack = call('GET', base + '/stacks/' + stack_id) + check('created-stack-owner-and-name', stack.get('name') == prefix + '-stack' and stack.get('accountId') == project['id']) + # No retry is sent to apply. An uncertain result is always a failure. + check('no-workloads-created', not call('GET', base + '/services?stackId=' + stack_id).get('data')) + finally: + # Revoke the ephemeral credential first. Each cleanup must still run + # when the other fails; either error keeps the smoke red and chained + # to the original failure. The publisher also owns the disposable DB. + try: + if key: + path = urlsplit(key['links']['self']).path; current = call('GET', path) + assert all(current.get(field) == key.get(field) for field in ('id', 'uuid', 'name')) + if current.get('state') == 'active': call('POST', path + '?action=deactivate', {}) + settled(path, lambda row: row.get('state') == 'inactive', 30) + call('DELETE', path) + finally: + if stack: + path = base + '/stacks/' + stack['id']; current = call('GET', path) + assert all(current.get(field) == stack.get(field) for field in ('id', 'uuid', 'name', 'accountId')) + assert not call('GET', base + '/services?stackId=' + stack['id']).get('data') + call('DELETE', path) + print('AI_RESOURCE_API_OK checks=' + str(len(checks)) + ' scoped_create_read=true process_pool=true human_cookie=true no_hosts=true', flush=True) diff --git a/scripts/test-current-server-packaging-contract.py b/scripts/test-current-server-packaging-contract.py index fbec3201bd..3548e55c87 100644 --- a/scripts/test-current-server-packaging-contract.py +++ b/scripts/test-current-server-packaging-contract.py @@ -39,10 +39,10 @@ WEB_SBOM_SHA = '324948a11348729a334864c04850a77b2e5c4643546168ee7b8c7289e983ac31' WEB_LOCK_SHA = 'e9f88f608cd4d516a69141464a6eb853ec1179bb86415979fad0569cdfa88173' CATALOG_COMMIT = '00eec89e5fdeb9728c1c41babccad8b7dfc8b297' -ENGINE_SHA = 'dfce4c6df625a905a837770780bd09d871752cf9d8493b590145f84a8c78dd09' -ENGINE_SOURCE = '24cfa1db113f54de3148cd4ac3191e66a1702806' +ENGINE_SHA = 'a46e832314b32292e3423133168020acf93052a7dd29e967bbaabc3df6dca8dc' +ENGINE_SOURCE = '2cd688b0c066658c41e7d3de5bed8c543687f275' OLD_COORDINATES = { - 'v1.6.556': 'v1.6.521', + 'v1.6.557': 'v1.6.521', '1.6.199': '1.6.181', WEB_SHA: '9199681f2c4311f3fbe8727fcf0f6fa136c9bafe9fbe9d13878c55df442a7a03', WEB_SOURCE: '7f2bdad0c90a3241693c2ddd4475202ababba550', @@ -60,13 +60,13 @@ ('LICENSE_SHA256', 'license_sha256', '0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594'), ) LEGACY_ENGINE_COORDINATES = { - '0.183.356': '0.183.337', + '0.183.357': '0.183.337', ENGINE_SHA: '7e45189f2b57097efc7929c04ddf7767aebbe027d1b9f90023aa6711522c5c80', ENGINE_SOURCE: 'ba041fe312dfe97fc1e5144af576ddcf1b573d8e', } EXPECTED = { COMPATIBILITY_CODE: (COMPATIBILITY, PUBLISHED_508), - 'SERVER_INCREMENTAL_RELEASE_DEFAULT_MISSING': (DOCKER, 'ARG SERVER_RELEASE_TAG=v1.6.556'), + 'SERVER_INCREMENTAL_RELEASE_DEFAULT_MISSING': (DOCKER, 'ARG SERVER_RELEASE_TAG=v1.6.557'), 'SERVER_INCREMENTAL_RELEASE_VERSION_MISSING': (DOCKER, 'org.opencontainers.image.version="${SERVER_RELEASE_TAG}"'), 'SERVER_INCREMENTAL_RELEASE_RUNTIME_VERSION_MISSING': (DOCKER, 'ENV CATTLE_RANCHER_SERVER_VERSION=${SERVER_RELEASE_TAG}'), 'SERVER_INCREMENTAL_WEB_CONSOLE_VERSION_MISSING': (DOCKER, 'ARG WEB_CONSOLE_RELEASE_TAG=1.6.199'), @@ -81,8 +81,8 @@ 'SERVER_INCREMENTAL_WEB_CONSOLE_BUILD_HASH_MISSING': (BUILD, 'web_console_artifact_sha256=${WEB_CONSOLE_ARTIFACT_SHA256:-' + WEB_SHA + '}'), 'SERVER_INCREMENTAL_WEB_CONSOLE_BUILD_LOCK_HASH_MISSING': (BUILD, 'web_console_lock_sha256=${WEB_CONSOLE_LOCK_SHA256:-' + WEB_LOCK_SHA + '}'), 'SERVER_INCREMENTAL_WEB_CONSOLE_BUILD_SBOM_HASH_MISSING': (BUILD, 'web_console_runtime_sbom_sha256=${WEB_CONSOLE_RUNTIME_SBOM_SHA256:-' + WEB_SBOM_SHA + '}'), - 'SERVER_INCREMENTAL_RELEASE_BUILD_VERSION_MISSING': (BUILD, 'image=${IMAGE:-pasturestack-validation/server:v1.6.556}'), - 'SERVER_INCREMENTAL_RELEASE_BUILD_DEFAULT_MISSING': (BUILD, 'server_release_tag=${SERVER_RELEASE_TAG:-v1.6.556}'), + 'SERVER_INCREMENTAL_RELEASE_BUILD_VERSION_MISSING': (BUILD, 'image=${IMAGE:-pasturestack-validation/server:v1.6.557}'), + 'SERVER_INCREMENTAL_RELEASE_BUILD_DEFAULT_MISSING': (BUILD, 'server_release_tag=${SERVER_RELEASE_TAG:-v1.6.557}'), 'SERVER_INCREMENTAL_RELEASE_BUILD_RUNTIME_VERSION_MISSING': (BUILD, 'CATTLE_RANCHER_SERVER_VERSION="${server_release_tag}"'), 'SERVER_WEB_CONSOLE_RUNTIME_VERSION_GATE_MISSING': (BUILD, 'test "$(cat "${web_root}/VERSION.txt")" = "${WEB_CONSOLE_RELEASE_TAG}"'), 'SERVER_VOLUME_NATIVE_READ_ONLY_BUILD_GATE_MISSING': (DOCKER, 'grep -F \'"volume.isNative" : "r"\' >/dev/null'), @@ -103,18 +103,18 @@ CREATE_RESPONSE_CODES = ['SERVER_WEB_CREATE_IDENTITY_BUILD_GATE_MISSING','SERVER_WEB_CANONICAL_RECORD_BUILD_GATE_MISSING','SERVER_WEB_CREATE_IDENTITY_RUNTIME_GATE_MISSING','SERVER_WEB_CANONICAL_RECORD_RUNTIME_GATE_MISSING'] ENGINE_EXPECTED = { 'SERVER_INCREMENTAL_ENGINE_REPLACEMENT_MISSING': (DOCKER, 'release_engine_marker', ( - 'ARG ORCHESTRATION_ENGINE_RELEASE_TAG=v0.183.356', + 'ARG ORCHESTRATION_ENGINE_RELEASE_TAG=v0.183.357', 'ARG ORCHESTRATION_ENGINE_ARTIFACT=cattle.jar', 'ARG ORCHESTRATION_ENGINE_ARTIFACT_SHA256=' + ENGINE_SHA, 'ARG ORCHESTRATION_ENGINE_COMMIT=' + ENGINE_SOURCE, - 'ARG ORCHESTRATION_ENGINE_VERSION=0.183.356', + 'ARG ORCHESTRATION_ENGINE_VERSION=0.183.357', 'sh /usr/share/cattle/verify-engine-archive.sh "${archive}" "${ORCHESTRATION_ENGINE_VERSION}" "${ORCHESTRATION_ENGINE_ARTIFACT_SHA256}"', 'cattle-resources-${ORCHESTRATION_ENGINE_VERSION}.jar', 'cattle-app-config-${ORCHESTRATION_ENGINE_VERSION}.jar', 'ENV CATTLE_CATTLE_VERSION=${ORCHESTRATION_ENGINE_RELEASE_TAG}', )), 'SERVER_INCREMENTAL_ENGINE_BUILD_COORDINATE_MISSING': (BUILD, 'release_engine_build_marker', ( - 'orchestration_engine_release_tag=${ORCHESTRATION_ENGINE_RELEASE_TAG:-v0.183.356}', + 'orchestration_engine_release_tag=${ORCHESTRATION_ENGINE_RELEASE_TAG:-v0.183.357}', 'orchestration_engine_artifact=${ORCHESTRATION_ENGINE_ARTIFACT:-cattle.jar}', 'orchestration_engine_artifact_sha256=${ORCHESTRATION_ENGINE_ARTIFACT_SHA256:-' + ENGINE_SHA + '}', 'orchestration_engine_commit=${ORCHESTRATION_ENGINE_COMMIT:-' + ENGINE_SOURCE + '}', @@ -608,15 +608,15 @@ def verify(files, gate=GATE): pipeline = r'(?:^|[;\n])\s*' + re.escape(marker) + r'(?=\s*(?:;|\n|$))' if len(re.findall(pipeline, source)) != 1: raise AssertionError('CURRENT_CATALOG_HASH_BYPASS') - if 'and .["@id"] == "https://github.com/PastureStack/server/security/openvex/v1.6.556"' not in gate: + if 'and .["@id"] == "https://github.com/PastureStack/server/security/openvex/v1.6.557"' not in gate: raise AssertionError('CURRENT_VEX_GATE_PIN_MISMATCH') - if '"$vendor_pending_fixture" v1.6.556 >/dev/null' not in gate: + if '"$vendor_pending_fixture" v1.6.557 >/dev/null' not in gate: raise AssertionError('CURRENT_VENDOR_GATE_PIN_MISMATCH') - if json.loads(files[VEX]).get('@id') != 'https://github.com/PastureStack/server/security/openvex/v1.6.556': + if json.loads(files[VEX]).get('@id') != 'https://github.com/PastureStack/server/security/openvex/v1.6.557': raise AssertionError('CURRENT_VEX_RELEASE_MISMATCH') - if json.loads(files[VENDOR]).get('release') != 'v1.6.556': + if json.loads(files[VENDOR]).get('release') != 'v1.6.557': raise AssertionError('CURRENT_VENDOR_RELEASE_MISMATCH') - if 'SERVER_API_EXPLORER_PATCH_OK release=v1.6.556 base=v1.6.460 engine=0.183.356 web_console=1.6.199 catalog_service=0.20.15 ' not in gate: + if 'SERVER_API_EXPLORER_PATCH_OK release=v1.6.557 base=v1.6.460 engine=0.183.357 web_console=1.6.199 catalog_service=0.20.15 ' not in gate: raise AssertionError('CURRENT_SUMMARY_MISMATCH') verify_incremental_contract(files, gate) verify_load_balancer_contract(files, gate) @@ -631,11 +631,11 @@ def previous_gate(gate=GATE): if stale(marker) != marker: replacements["'" + marker + "' "] = "'" + stale(marker) + "' " replacements.update({ - 'and .["@id"] == "https://github.com/PastureStack/server/security/openvex/v1.6.556"': + 'and .["@id"] == "https://github.com/PastureStack/server/security/openvex/v1.6.557"': 'and .["@id"] == "https://github.com/PastureStack/server/security/openvex/v1.6.521"', - '"$vendor_pending_fixture" v1.6.556 >/dev/null': + '"$vendor_pending_fixture" v1.6.557 >/dev/null': '"$vendor_pending_fixture" v1.6.521 >/dev/null', - 'SERVER_API_EXPLORER_PATCH_OK release=v1.6.556 base=v1.6.460 engine=0.183.356 web_console=1.6.199 catalog_service=0.20.15 ': + 'SERVER_API_EXPLORER_PATCH_OK release=v1.6.557 base=v1.6.460 engine=0.183.357 web_console=1.6.199 catalog_service=0.20.15 ': 'SERVER_API_EXPLORER_PATCH_OK release=v1.6.521 base=v1.6.460 engine=0.183.340 web_console=1.6.181 catalog_service=0.20.12 ', }) for marker, stale_marker in replacements.items(): @@ -1299,7 +1299,7 @@ def test_each_old_engine_coordinate_rejected(self): self.assertGreater(checked, 0) def test_historical_engine340_cannot_be_packaged(self): - old = {'0.183.356': '0.183.340', + old = {'0.183.357': '0.183.340', ENGINE_SHA: '5e5a1b908b43bf3824fc3bb2108bd661cd5199ce9bcfd187e0b18b5608a38cea', ENGINE_SOURCE: 'ff0a41e7676211043eb4f755a306a9e2a19abee1'} checked = 0 @@ -1320,13 +1320,13 @@ def test_historical_engine340_cannot_be_packaged(self): def test_engine352_actual_war_producer_and_previous351_350_boundary(self): candidate = (REPO / 'server/build-component-candidate.sh').read_text(encoding='utf-8') - self.assertIn('export SERVER_RELEASE_TAG=${SERVER_RELEASE_TAG:-v1.6.556}', candidate) - self.assertIn('export ORCHESTRATION_ENGINE_RELEASE_TAG=${ORCHESTRATION_ENGINE_RELEASE_TAG:-v0.183.356}', candidate) + self.assertIn('export SERVER_RELEASE_TAG=${SERVER_RELEASE_TAG:-v1.6.557}', candidate) + self.assertIn('export ORCHESTRATION_ENGINE_RELEASE_TAG=${ORCHESTRATION_ENGINE_RELEASE_TAG:-v0.183.357}', candidate) for old in ( - {'0.183.356': '0.183.351', + {'0.183.357': '0.183.351', ENGINE_SHA: 'efd0e826364c551f782b281f081d53cadb48faa7d5c37c2f101e6f9c7d7f9ea6', ENGINE_SOURCE: '1befd83278618f9a5b7cdaf96522004dd89918ba'}, - {'0.183.356': '0.183.350', + {'0.183.357': '0.183.350', ENGINE_SHA: '637ddaa42cd93c019b4d0813d7053b71dc42797a7f3ac2aa4b10fcc7e304cb31', ENGINE_SOURCE: '9c884710e5ea3d4136d80a870d9de9485674f3c3'}, {ENGINE_SOURCE: '109f2623f00ca3a3a9079414a0f0f8bd23cd1eb2'}, @@ -1349,7 +1349,7 @@ def test_engine352_actual_war_producer_and_previous351_350_boundary(self): def test_immediately_previous_engine341_cannot_be_packaged(self): - old = {'0.183.356': '0.183.341', + old = {'0.183.357': '0.183.341', ENGINE_SHA: '3ede1ad28b7a7e0754c4c953bd486162f7ffe0b2f76ce384ec485632af6b8e6d', ENGINE_SOURCE: 'b245cf778479445ded0786d3898b03fea153212e'} checked = 0 @@ -1370,7 +1370,7 @@ def test_immediately_previous_engine341_cannot_be_packaged(self): def test_immediately_previous_engine342_cannot_be_packaged(self): - old = {'0.183.356': '0.183.342', + old = {'0.183.357': '0.183.342', ENGINE_SHA: '3533f247392795329c92516a7966510aafbe81a52e3f922e5ec657a2071363b5', ENGINE_SOURCE: 'ddae4bb8e12806f70816f5782cd999eccd0f2ce6'} checked = 0 @@ -1391,7 +1391,7 @@ def test_immediately_previous_engine342_cannot_be_packaged(self): def test_immediately_previous_engine343_cannot_be_packaged(self): - old = {'0.183.356': '0.183.343', + old = {'0.183.357': '0.183.343', ENGINE_SHA: 'b29c0057f96dbae38bfe2c663c63bbe4c8b5c755b3090f39414aa51f9813025f', ENGINE_SOURCE: '5aa9d8978c75a7fe63330453c399a92716d88568'} checked = 0 @@ -1412,7 +1412,7 @@ def test_immediately_previous_engine343_cannot_be_packaged(self): def test_immediately_previous_engine344_cannot_be_packaged(self): - old = {'0.183.356': '0.183.344', + old = {'0.183.357': '0.183.344', ENGINE_SHA: 'ffafa4700156b74ec11bcae1b830738e49943f1a3b8b0565895ed6d7726eebf1', ENGINE_SOURCE: '72c42e6f2000301fe03ffd2442fb9ee89aee120c'} checked = 0 @@ -1432,7 +1432,7 @@ def test_immediately_previous_engine344_cannot_be_packaged(self): self.assertGreater(checked, 0) def test_immediately_previous_engine345_cannot_be_packaged(self): - old = {'0.183.356': '0.183.345', + old = {'0.183.357': '0.183.345', ENGINE_SHA: '780263c4a884527fa80a28b998ad4bda88b9ad6002a687f9f074602ecad46e62', ENGINE_SOURCE: 'd27d4ac73fa05ae43b9ae0c32875780e8a3765b1'} checked = 0 @@ -1452,7 +1452,7 @@ def test_immediately_previous_engine345_cannot_be_packaged(self): self.assertGreater(checked, 0) def test_immediately_previous_engine346_cannot_be_packaged(self): - old = {'0.183.356': '0.183.346', + old = {'0.183.357': '0.183.346', ENGINE_SHA: '9deeda5758b7f04135441a203092dd0308d90b65d25037b62ef4f9361d3cf806', ENGINE_SOURCE: 'e250e4a17958216c30c1f5d0d31f7b6418a968d5'} checked = 0 @@ -1628,7 +1628,7 @@ def test_machine_actual_binary_package_and_retired_boundary_are_verified(self): def test_current_readme_status_specific_prose_does_not_block_publication_transition(self): common = GATE.split('for current_readme_marker in ', 1)[1].split('; do', 1)[0] self.assertNotIn('candidate', common) - self.assertNotIn('v1.6.556', common) + self.assertNotIn('v1.6.557', common) self.assertIn("grep -Fqi 'keep all three named volumes' README.md", GATE) status = GATE.split("if grep -Fxq '## Current source candidate' README.md; then", 1)[1] candidate, published = status.split("elif grep -Fxq '## Current release' README.md; then", 1) @@ -1637,7 +1637,7 @@ def test_current_readme_status_specific_prose_does_not_block_publication_transit self.assertIn('This candidate is not yet available', candidate) self.assertIn('SERVER_CURRENT_PUBLISHED_README_MISSING', published) self.assertNotIn('candidate', published) - self.assertNotIn('v1.6.556', published) + self.assertNotIn('v1.6.557', published) if __name__ == '__main__': diff --git a/scripts/test-mfa-policy-api.py b/scripts/test-mfa-policy-api.py index 5d71c6fbf5..5d43de2fe4 100644 --- a/scripts/test-mfa-policy-api.py +++ b/scripts/test-mfa-policy-api.py @@ -25,6 +25,8 @@ def main(): parser.add_argument('--api-version', choices=('v1', 'v2-beta'), default='v2-beta') parser.add_argument('--registration-basic', action='store_true', help='Run native registration entry checks using this same fresh administrator session.') + parser.add_argument('--ai-resource', action='store_true', + help='Qualify opt-in typed-resource contracts with this same disposable administrator session.') args = parser.parse_args() assert 1 <= args.port <= 65535 # Fixed loopback authority: callers cannot supply a remote URL, and the @@ -108,6 +110,14 @@ def verify_session_bound_token(api_root, issued_token, generation, label): registration.run(port=args.port, administrator_jwt=token, administrator_account_id=login['accountId'], disposable=args.disposable) + if args.ai_resource: + spec = importlib.util.spec_from_file_location('ai_resource_smoke', + Path(__file__).with_name('test-ai-resource-api.py')) + ai_resource = importlib.util.module_from_spec(spec) + spec.loader.exec_module(ai_resource) + ai_resource.run(port=args.port, administrator_jwt=token, + administrator_account_id=login['accountId'], disposable=args.disposable) + # The token resource intentionally has no public schema entry. Its # clientSessionId contract is therefore verified below through observable # issue/delete semantics: a mismatched generation must preserve the token, diff --git a/server/Dockerfile.web-compose-release b/server/Dockerfile.web-compose-release index 767b7755a5..e806e1c5b9 100644 --- a/server/Dockerfile.web-compose-release +++ b/server/Dockerfile.web-compose-release @@ -118,9 +118,9 @@ ARG WEBHOOK_AUTOMATION_SERVICE_VERSION=0.10.5 ARG WEBHOOK_AUTOMATION_SERVICE_ARCHIVE_SHA256=f2df8874d5a00a2d5713594609063256164ed624d29a733149d00cb271f0f66b ARG WEBHOOK_AUTOMATION_SERVICE_BINARY_SHA256=b98e55db2739ab45119eacc94c8f65cb44371480ebcebec95e5470fd67c72a4c ARG ORCHESTRATION_ENGINE_RELEASE_BASE_URL=https://github.com/PastureStack/orchestration-engine/releases/download -ARG ORCHESTRATION_ENGINE_RELEASE_TAG=v0.183.356 +ARG ORCHESTRATION_ENGINE_RELEASE_TAG=v0.183.357 ARG ORCHESTRATION_ENGINE_ARTIFACT=cattle.jar -ARG ORCHESTRATION_ENGINE_ARTIFACT_SHA256=dfce4c6df625a905a837770780bd09d871752cf9d8493b590145f84a8c78dd09 +ARG ORCHESTRATION_ENGINE_ARTIFACT_SHA256=a46e832314b32292e3423133168020acf93052a7dd29e967bbaabc3df6dca8dc ARG COMPOSE_EXECUTOR_RELEASE_BASE_URL=https://github.com/PastureStack/compose-cli/releases/download ARG COMPOSE_EXECUTOR_VERSION=0.14.39 ARG COMPOSE_EXECUTOR_ARCHIVE_SHA256=4ab4685af67a8b8b11f3dd4996de9e087c26391ec401cf02cdcafe4c93094bab @@ -696,12 +696,12 @@ ARG PER_HOST_SUBNET_VERSION=0.2.5 ARG PER_HOST_SUBNET_PRODUCER_COMMIT=e102e0bb38d84b0a9cbf87e5458cf1bc74d01904 ARG PER_HOST_SUBNET_ARCHIVE_SHA256=7237e83e96a64e7f3de64eb86bff9721c4e879c35cda9e9de1e4cb1ba225f298 ARG PER_HOST_SUBNET_PROVENANCE_SHA256=afa2db0e0755c6bd3ee28e111937c521a6d84e6d71d563e99202cf4693000eaf -ARG SERVER_RELEASE_TAG=v1.6.556 +ARG SERVER_RELEASE_TAG=v1.6.557 ARG API_EXPLORER_RELEASE_TAG=v1.1.20 ARG API_EXPLORER_ARTIFACT_SHA256=c989ee12a518f6d9d2b23b1f17f48d781aacf6ec31fb65291dd7de9b1661badb ARG API_EXPLORER_COMMIT=a586f0dc0aa50df579049a8d4bf26f04400fdf75 -ARG ORCHESTRATION_ENGINE_RELEASE_TAG=v0.183.356 -ARG ORCHESTRATION_ENGINE_VERSION=0.183.356 +ARG ORCHESTRATION_ENGINE_RELEASE_TAG=v0.183.357 +ARG ORCHESTRATION_ENGINE_VERSION=0.183.357 ARG ENGINE_READONLY_SCHEMA_SHA256=7f274219e8dd9c6d750a408a6edec1448b564f4b16ba2204c425c5b45cec2233 ARG ENGINE_RESTRICTED_SCHEMA_SHA256=f854ba99260f29e324ab7446a8592996946038920ac9bcf17689d98d1ebc5e51 ARG HOST_API_VERSION=0.38.8 @@ -745,8 +745,8 @@ ARG WEBHOOK_AUTOMATION_SERVICE_VERSION=0.10.5 ARG WEBHOOK_AUTOMATION_SERVICE_COMMIT=4da77ccac464bc7f7cd2020e0659a666a5d1ff7e ARG WEBHOOK_AUTOMATION_SERVICE_ARCHIVE_SHA256=f2df8874d5a00a2d5713594609063256164ed624d29a733149d00cb271f0f66b ARG WEBHOOK_AUTOMATION_SERVICE_BINARY_SHA256=b98e55db2739ab45119eacc94c8f65cb44371480ebcebec95e5470fd67c72a4c -ARG ORCHESTRATION_ENGINE_ARTIFACT_SHA256=dfce4c6df625a905a837770780bd09d871752cf9d8493b590145f84a8c78dd09 -ARG ORCHESTRATION_ENGINE_COMMIT=24cfa1db113f54de3148cd4ac3191e66a1702806 +ARG ORCHESTRATION_ENGINE_ARTIFACT_SHA256=a46e832314b32292e3423133168020acf93052a7dd29e967bbaabc3df6dca8dc +ARG ORCHESTRATION_ENGINE_COMMIT=2cd688b0c066658c41e7d3de5bed8c543687f275 ARG HOST_PROVISIONER_VERSION=0.39.10 ARG HOST_PROVISIONER_COMMIT=d5f6d5c9f4f0599f4bf1bdc9d5d0cca2e2e0c1ba ARG HOST_PROVISIONER_ARCHIVE_SHA256=fd8a814c5810746091ba3192a9fd31699e6865a2598654b9bbb55eae90bef661 diff --git a/server/build-api-explorer-patch-image.sh b/server/build-api-explorer-patch-image.sh index f423009fe0..355b03a046 100755 --- a/server/build-api-explorer-patch-image.sh +++ b/server/build-api-explorer-patch-image.sh @@ -14,14 +14,14 @@ if [[ -n "$(git status --porcelain --untracked-files=normal)" ]]; then fi revision=${PASTURESTACK_SERVER_REVISION:-$(git rev-parse HEAD)} -server_release_tag=${SERVER_RELEASE_TAG:-v1.6.556} +server_release_tag=${SERVER_RELEASE_TAG:-v1.6.557} source_date_epoch=${SOURCE_DATE_EPOCH:-$(git show -s --format=%ct HEAD)} base_image=${BASE_IMAGE:-ghcr.io/pasturestack/server:v1.6.460@sha256:c855af8aea232dacc5bb6df68e2271d482c68b53c43ab0c108ec19118f5ab403} orchestration_engine_release_base_url=${ORCHESTRATION_ENGINE_RELEASE_BASE_URL:-https://github.com/PastureStack/orchestration-engine/releases/download} -orchestration_engine_release_tag=${ORCHESTRATION_ENGINE_RELEASE_TAG:-v0.183.356} +orchestration_engine_release_tag=${ORCHESTRATION_ENGINE_RELEASE_TAG:-v0.183.357} orchestration_engine_artifact=${ORCHESTRATION_ENGINE_ARTIFACT:-cattle.jar} -orchestration_engine_artifact_sha256=${ORCHESTRATION_ENGINE_ARTIFACT_SHA256:-dfce4c6df625a905a837770780bd09d871752cf9d8493b590145f84a8c78dd09} -orchestration_engine_commit=${ORCHESTRATION_ENGINE_COMMIT:-24cfa1db113f54de3148cd4ac3191e66a1702806} +orchestration_engine_artifact_sha256=${ORCHESTRATION_ENGINE_ARTIFACT_SHA256:-a46e832314b32292e3423133168020acf93052a7dd29e967bbaabc3df6dca8dc} +orchestration_engine_commit=${ORCHESTRATION_ENGINE_COMMIT:-2cd688b0c066658c41e7d3de5bed8c543687f275} orchestration_engine_version=${orchestration_engine_release_tag#v} engine_readonly_schema_sha256=${ENGINE_READONLY_SCHEMA_SHA256:-7f274219e8dd9c6d750a408a6edec1448b564f4b16ba2204c425c5b45cec2233} engine_restricted_schema_sha256=${ENGINE_RESTRICTED_SCHEMA_SHA256:-f854ba99260f29e324ab7446a8592996946038920ac9bcf17689d98d1ebc5e51} @@ -130,7 +130,7 @@ usage_telemetry_agent_archive_sha256=${USAGE_TELEMETRY_AGENT_ARCHIVE_SHA256:-6d4 usage_telemetry_agent_binary_sha256=${USAGE_TELEMETRY_AGENT_BINARY_SHA256:-90ed65f689c91801abd0cf482211c96a01e7c63ef695e4faecdf4713eff730be} supported_docker_range='~v1.12.3 || ~v1.13.0 || ~v17.03.0 || ~v17.06.0 || ~v17.09.0 || ~v17.12.0 || ~v18.03.0 || ~v18.06.0 || ~v18.09.0 || ~v19.03.2 || v24.0.9 || >=v29.4.1 <=v29.7.2 || v29.8.0' newest_docker_version=v29.8.0 -image=${IMAGE:-pasturestack-validation/server:v1.6.556} +image=${IMAGE:-pasturestack-validation/server:v1.6.557} build_options=() [[ "$revision" =~ ^[0-9a-f]{40}$ ]] diff --git a/server/build-component-candidate.sh b/server/build-component-candidate.sh index f0ffa577c6..23489f45c2 100755 --- a/server/build-component-candidate.sh +++ b/server/build-component-candidate.sh @@ -18,8 +18,8 @@ for name in "${required[@]}"; do case "$name" in *_COMMIT) [[ ${!name} =~ ^[0-9a-f]{40}$ ]] ;; *) [[ ${!name} =~ ^[0-9a-f]{64}$ ]] ;; esac export "$name" done -export SERVER_RELEASE_TAG=${SERVER_RELEASE_TAG:-v1.6.556} -export ORCHESTRATION_ENGINE_RELEASE_TAG=${ORCHESTRATION_ENGINE_RELEASE_TAG:-v0.183.356} +export SERVER_RELEASE_TAG=${SERVER_RELEASE_TAG:-v1.6.557} +export ORCHESTRATION_ENGINE_RELEASE_TAG=${ORCHESTRATION_ENGINE_RELEASE_TAG:-v0.183.357} export ORCHESTRATION_ENGINE_ARTIFACT=cattle.jar export WEB_CONSOLE_RELEASE_TAG=${WEB_CONSOLE_RELEASE_TAG:-1.6.199} export WEB_CONSOLE_ARTIFACT="web-console-${WEB_CONSOLE_RELEASE_TAG}.tar.gz" diff --git a/server/security/openvex.json b/server/security/openvex.json index d7ae51adf3..27a7377205 100644 --- a/server/security/openvex.json +++ b/server/security/openvex.json @@ -1,9 +1,9 @@ { "@context": "https://openvex.dev/ns/v0.2.0", - "@id": "https://github.com/PastureStack/server/security/openvex/v1.6.556", + "@id": "https://github.com/PastureStack/server/security/openvex/v1.6.557", "author": "PastureStack Security", - "timestamp": "2026-10-29T17:05:21Z", - "version": 68, + "timestamp": "2026-10-29T18:11:24Z", + "version": 69, "statements": [ { "vulnerability": { diff --git a/server/security/vendor-pending.json b/server/security/vendor-pending.json index a2cc1e17a9..b326f48908 100644 --- a/server/security/vendor-pending.json +++ b/server/security/vendor-pending.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "release": "v1.6.556", + "release": "v1.6.557", "generatedAt": "2026-10-29T09:57:33.809116+00:00", "policy": { "allowedSeverities": [