From de1dde1e9dff59b1f8527b90fa7f48683634cfd3 Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Sat, 3 Oct 2026 05:48:18 +0800 Subject: [PATCH] fix(volume): expose server-owned native classification in v1 and v2 --- .github/workflows/security-release-gate.yml | 14 ++ COMPATIBILITY.md | 14 ++ README.md | 10 +- code/framework/api-pub-sub-jetty/pom.xml | 2 +- code/framework/api-pub-sub/pom.xml | 2 +- code/framework/api/pom.xml | 2 +- .../api/schema/FileSchemaFactory.java | 24 ++++ .../api/schema/FileSchemaFactoryTest.java | 65 +++++++++ code/framework/archaius/pom.xml | 2 +- code/framework/async/pom.xml | 2 +- code/framework/auditing/pom.xml | 2 +- code/framework/db-loader/pom.xml | 2 +- code/framework/deferred/pom.xml | 2 +- code/framework/encryption/pom.xml | 2 +- code/framework/engine/pom.xml | 2 +- code/framework/eventing/pom.xml | 2 +- code/framework/events/pom.xml | 2 +- code/framework/extension-spring/pom.xml | 2 +- code/framework/extension/pom.xml | 2 +- code/framework/java-server/pom.xml | 2 +- .../impl/VolumeNativeWrappedResourceTest.java | 45 +++++++ .../validation/ValidationHandlerTest.java | 22 +++ code/framework/jmx/pom.xml | 2 +- code/framework/jooq/pom.xml | 2 +- code/framework/json/pom.xml | 2 +- code/framework/launcher/pom.xml | 2 +- code/framework/lock/pom.xml | 2 +- code/framework/logback/pom.xml | 2 +- code/framework/managed-context/pom.xml | 2 +- code/framework/metrics/pom.xml | 2 +- code/framework/module/pom.xml | 2 +- code/framework/object/pom.xml | 2 +- code/framework/pool/pom.xml | 2 +- code/framework/resource-monitor/pom.xml | 2 +- code/framework/schema/pom.xml | 2 +- .../VolumeNativeSchemaAuthorizationTest.java | 126 ++++++++++++++++++ code/framework/server/pom.xml | 2 +- code/framework/spring/pom.xml | 2 +- code/framework/system-task/pom.xml | 2 +- code/framework/token/pom.xml | 2 +- code/framework/utils/pom.xml | 2 +- code/iaas/agent-instance/pom.xml | 2 +- code/iaas/agent-server/pom.xml | 2 +- code/iaas/agent/pom.xml | 2 +- code/iaas/allocator/pom.xml | 2 +- code/iaas/api-logic/pom.xml | 2 +- code/iaas/archaius-management/pom.xml | 2 +- code/iaas/auth-logic/pom.xml | 2 +- code/iaas/bootstrap/pom.xml | 2 +- code/iaas/config-item/api/pom.xml | 2 +- code/iaas/config-item/common/pom.xml | 2 +- code/iaas/config-item/server/pom.xml | 2 +- code/iaas/engine-jooq/pom.xml | 2 +- code/iaas/events/pom.xml | 2 +- code/iaas/external-handler/pom.xml | 2 +- code/iaas/ha/pom.xml | 2 +- code/iaas/healthcheck/pom.xml | 2 +- code/iaas/labels/pom.xml | 2 +- code/iaas/logic-common/pom.xml | 2 +- code/iaas/logic/pom.xml | 2 +- code/iaas/metadata/pom.xml | 2 +- code/iaas/model/pom.xml | 2 +- code/iaas/resource-pool/pom.xml | 2 +- code/iaas/service-discovery/api/pom.xml | 2 +- code/iaas/service-discovery/server/pom.xml | 2 +- code/iaas/ssh-common/pom.xml | 2 +- code/iaas/storage-service/pom.xml | 2 +- code/iaas/task-jooq/pom.xml | 2 +- code/implementation/activity-log/pom.xml | 2 +- .../agent-instance-impl/pom.xml | 2 +- code/implementation/docker/api/pom.xml | 2 +- code/implementation/docker/common/pom.xml | 2 +- code/implementation/docker/compute/pom.xml | 2 +- code/implementation/docker/machine/pom.xml | 2 +- code/implementation/docker/storage/pom.xml | 6 +- code/implementation/extension-api/pom.xml | 2 +- code/implementation/hazelcast/common/pom.xml | 2 +- .../implementation/hazelcast/eventing/pom.xml | 2 +- code/implementation/hazelcast/lock/pom.xml | 2 +- code/implementation/host-api/pom.xml | 2 +- code/implementation/host-stats/pom.xml | 2 +- code/implementation/register/pom.xml | 2 +- code/implementation/sample-setup/pom.xml | 2 +- code/implementation/settings-api/pom.xml | 2 +- .../simulator/agent-connection/pom.xml | 2 +- code/implementation/simulator/storage/pom.xml | 2 +- code/implementation/system-stack/pom.xml | 2 +- code/implementation/vm/pom.xml | 2 +- code/meta-parent/pom.xml | 2 +- code/packaging/app-config/pom.xml | 2 +- code/packaging/app/pom.xml | 2 +- code/packaging/bundle/pom.xml | 2 +- code/packaging/dev/pom.xml | 2 +- code/packaging/meta/pom.xml | 2 +- code/parent/pom.xml | 2 +- .../orchestration-engine-0.183.332.md | 47 +++++++ pom.xml | 2 +- resources/content/schema/user/user-auth.json | 1 + resources/pom.xml | 2 +- scripts/build | 2 +- scripts/check-pasturestack-source | 6 +- scripts/check-release-artifact | 2 +- 102 files changed, 464 insertions(+), 96 deletions(-) create mode 100644 code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/VolumeNativeWrappedResourceTest.java create mode 100644 code/framework/schema/src/test/java/io/cattle/platform/schema/processor/VolumeNativeSchemaAuthorizationTest.java create mode 100644 docs/releases/orchestration-engine-0.183.332.md diff --git a/.github/workflows/security-release-gate.yml b/.github/workflows/security-release-gate.yml index 9b7c50d688..822578f908 100644 --- a/.github/workflows/security-release-gate.yml +++ b/.github/workflows/security-release-gate.yml @@ -57,6 +57,20 @@ jobs: import xml.etree.ElementTree as ET required = { + 'io.cattle.platform.api.schema.FileSchemaFactoryTest': { + 'restoresOnlyNativeReadFieldInPackagedFrozenVolumeRoleSchemas', + }, + 'io.cattle.platform.schema.processor.VolumeNativeSchemaAuthorizationTest': { + 'currentRoleOverlaysExposeNativeClassificationWithoutGrantingMutation', + 'readonlyPipelinePreservesCrudWhileRetainingServerOwnedNativeReadField', + }, + 'io.github.ibuildthecloud.gdapi.model.impl.VolumeNativeWrappedResourceTest': { + 'formatterRetainsTheActualServerTrueAndFalseClassification', + 'onlyAnExplicitSchemaContractCanProvideTheServerDefault', + }, + 'io.github.ibuildthecloud.gdapi.validation.ValidationHandlerTest': { + 'clientCannotSetServerOwnedVolumeNativeClassification', + }, 'io.cattle.platform.core.dao.impl.NativeContainerNameRefreshDaoTest': { 'exactExistingImportedSnapshotAndNameOnlyCas', 'compareAndSwapContainsEveryOriginalColumnIncludingBinaryTextAndJson', diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index b866f96af7..28940d2310 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -4,6 +4,20 @@ The migration preserves established `io.cattle.*` Java packages, Maven coordinat New operator-facing names use PastureStack and `PASTURESTACK_*`. Compatibility identifiers must be changed only with an explicit data migration, a dual-read or dual-write transition, a rollback plan, and cross-repository verification. +## Volume native classification + +Candidate `0.183.332` exposes the existing `volume.isNative` boolean as read-only +for readable Volume resources. Current role overlays retain the field; the v1 +loader copies only this missing field from the current core schema into frozen +role schemas. It grants neither create nor update permission on the field and +does not widen collection/object authorization, methods, actions or other +fields. The API preserves stored true/false values and applies the established +server default only through an explicit schema contract. Client input cannot +set this server-owned classification on POST or PUT. No database migration is +required. Rolling back removes the field from affected role responses, so the +strict Web Console unallocated-volume list may again hide eligible volumes. +Native UI lifecycle acceptance and artifact publication are still pending. + ## Certificate lifecycle Engine `0.183.327` allows partial Certificate updates that omit `cert`, without diff --git a/README.md b/README.md index 15ff0fd887..fb928513b3 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,14 @@ preserved upstream boundary. ## Current release +Candidate `v0.183.332` restores the server-owned Volume `isNative` classification +as a read-only field in both v1 frozen role schemas and v2 role overlays. It does +not change Volume CRUD permissions, infer missing fields in the browser, or +allow clients to change native classification. Eighteen targeted local tests +passed, including six new regressions. Formal artifact publication and native +Volume UI lifecycle acceptance are pending; see the +[332 candidate note](docs/releases/orchestration-engine-0.183.332.md). + The published release `v0.183.331` corrects the stopped-container mapping condition in 330. The common selection/update predicate accepts only running/active or stopped/inactive pairs; all source-account, unique-mapping, managed-container @@ -206,7 +214,7 @@ bash scripts/check-cattle-jdk25-full-package After the gate passes, package and check the release artifact: ```sh -ENGINE_VERSION=0.183.331 bash scripts/build --release +ENGINE_VERSION=0.183.332 bash scripts/build --release bash scripts/check-release-artifact dist/artifacts/cattle.jar ``` diff --git a/code/framework/api-pub-sub-jetty/pom.xml b/code/framework/api-pub-sub-jetty/pom.xml index 44c868aec5..542ba068e3 100644 --- a/code/framework/api-pub-sub-jetty/pom.xml +++ b/code/framework/api-pub-sub-jetty/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/api-pub-sub/pom.xml b/code/framework/api-pub-sub/pom.xml index 271d8de9c5..3b0345b4ab 100644 --- a/code/framework/api-pub-sub/pom.xml +++ b/code/framework/api-pub-sub/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/api/pom.xml b/code/framework/api/pom.xml index 945a59497a..a381c83636 100644 --- a/code/framework/api/pom.xml +++ b/code/framework/api/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/api/src/main/java/io/cattle/platform/api/schema/FileSchemaFactory.java b/code/framework/api/src/main/java/io/cattle/platform/api/schema/FileSchemaFactory.java index 6f8a8b5a0b..ff64691086 100644 --- a/code/framework/api/src/main/java/io/cattle/platform/api/schema/FileSchemaFactory.java +++ b/code/framework/api/src/main/java/io/cattle/platform/api/schema/FileSchemaFactory.java @@ -92,6 +92,7 @@ protected void copyAccessors(Schema schema) { Schema coreSchema = parentSchemaFactory.getSchema(schema.getId()); mergeProjectMemberExternalIdTypeOptions(schema, coreSchema); mergeProjectTemplatePublicReadField(schema, coreSchema); + mergeVolumeNativeReadField(schema, coreSchema); Class clz = parentSchemaFactory.getSchemaClass(schema.getId()); if (clz == null) { return; @@ -157,6 +158,29 @@ public String getFile() { return file; } + protected void mergeVolumeNativeReadField(Schema schema, Schema parentSchema) { + if (parentSchema == null || !"volume".equals(schema.getId()) || + schema.getResourceFields().containsKey("isNative")) { + return; + } + + Field parentField = parentSchema.getResourceFields().get("isNative"); + if (!(parentField instanceof FieldImpl)) { + return; + } + + // v1 reads frozen role schemas, so the current authorization overlay + // cannot restore this missing classification. Expose only the existing + // server-owned flag; do not grant mutation or replace other fields. + FieldImpl readOnly = new FieldImpl(parentField); + readOnly.setName("isNative"); + readOnly.setCreate(false); + readOnly.setUpdate(false); + readOnly.setReadOnCreateOnly(false); + readOnly.setIncludeInList(true); + schema.getResourceFields().put("isNative", readOnly); + } + public void setFile(String file) { this.file = file; } diff --git a/code/framework/api/src/test/java/io/cattle/platform/api/schema/FileSchemaFactoryTest.java b/code/framework/api/src/test/java/io/cattle/platform/api/schema/FileSchemaFactoryTest.java index ae54e0b76e..0cb2ec468b 100644 --- a/code/framework/api/src/test/java/io/cattle/platform/api/schema/FileSchemaFactoryTest.java +++ b/code/framework/api/src/test/java/io/cattle/platform/api/schema/FileSchemaFactoryTest.java @@ -212,6 +212,71 @@ private FileSchemaFactory factory(String resourceName) { return factory(resourceName, new EmptySchemaFactory()); } + @Test + public void restoresOnlyNativeReadFieldInPackagedFrozenVolumeRoleSchemas() throws Exception { + SchemaImpl core = schema("volume", "volumes"); + FieldImpl coreField = new FieldImpl(); + coreField.setName("isNative"); + coreField.setType("boolean"); + coreField.setDefault(Boolean.FALSE); + // Even a more permissive parent cannot grant writes through this merge. + coreField.setCreate(true); + coreField.setUpdate(true); + core.getResourceFields().put("isNative", coreField); + Path root = Paths.get("").toAbsolutePath(); + while (root != null && !Files.isRegularFile(root.resolve("resources/content/schema/v1/owner.ser"))) { + root = root.getParent(); + } + assertNotNull("Packaged frozen role schemas are required", root); + for (String role : Arrays.asList("owner", "member", "readonly", "restricted", "user", "admin")) { + String resourceName = "schema/v1/" + role + ".ser"; + byte[] bytes = Files.readAllBytes(root.resolve("resources/content/").resolve(resourceName)); + Thread.currentThread().setContextClassLoader(new ResourceClassLoader(resourceName, bytes)); + FileSchemaFactory original = factory(resourceName); + original.start(); + Thread.currentThread().setContextClassLoader(new ResourceClassLoader(resourceName, bytes)); + FileSchemaFactory repaired = factory(resourceName, new SingleSchemaFactory(core)); + repaired.start(); + + Schema before = original.getSchema("volume"), after = repaired.getSchema("volume"); + assertNotNull(role, before); + assertNotNull(role, after); + Map originalFields = new LinkedHashMap(); + for (Map.Entry entry : before.getResourceFields().entrySet()) { + originalFields.put(entry.getKey(), (FieldImpl) entry.getValue()); + } + FieldImpl actual = (FieldImpl) after.getResourceFields().get("isNative"); + assertNotNull(role, actual); + assertEquals(role, "boolean", actual.getType()); + assertEquals(role, Boolean.FALSE, actual.getDefault()); + assertFalse(role, actual.isNullable()); + assertFalse(role, actual.isCreate()); + assertFalse(role, actual.isUpdate()); + assertFalse(role, actual.isReadOnCreateOnly()); + assertTrue(role, actual.isIncludeInList()); + assertEquals(role, before.getCollectionMethods(), after.getCollectionMethods()); + assertEquals(role, before.getResourceMethods(), after.getResourceMethods()); + assertTrue(role + "/resourceActions", Arrays.equals( + serialize(Arrays.asList(before.getResourceActions())), + serialize(Arrays.asList(after.getResourceActions())))); + assertTrue(role + "/collectionActions", Arrays.equals( + serialize(Arrays.asList(before.getCollectionActions())), + serialize(Arrays.asList(after.getCollectionActions())))); + for (Map.Entry entry : originalFields.entrySet()) { + if (!"isNative".equals(entry.getKey())) { + assertTrue(role, after.getResourceFields().containsKey(entry.getKey())); + assertTrue(role + "/" + entry.getKey(), Arrays.equals( + serialize(Arrays.asList(entry.getValue())), + serialize(Arrays.asList(after.getResourceFields().get(entry.getKey()))))); + } + } + assertEquals(role, originalFields.size() + (originalFields.containsKey("isNative") ? 0 : 1), + after.getResourceFields().size()); + } + assertTrue("Parent permissions must remain unchanged", coreField.isCreate()); + assertTrue(coreField.isUpdate()); + } + private FileSchemaFactory factory(String resourceName, SchemaFactory schemaFactory) { FileSchemaFactory factory = new FileSchemaFactory(); factory.setFile(resourceName); diff --git a/code/framework/archaius/pom.xml b/code/framework/archaius/pom.xml index d92a7eae4a..d8b4a3cdc2 100644 --- a/code/framework/archaius/pom.xml +++ b/code/framework/archaius/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-meta-parent - 0.183.331 + 0.183.332 ../../meta-parent/pom.xml diff --git a/code/framework/async/pom.xml b/code/framework/async/pom.xml index 65c8dbb18a..ef369bfb54 100644 --- a/code/framework/async/pom.xml +++ b/code/framework/async/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/auditing/pom.xml b/code/framework/auditing/pom.xml index 5aa26a8453..70434a0304 100644 --- a/code/framework/auditing/pom.xml +++ b/code/framework/auditing/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/db-loader/pom.xml b/code/framework/db-loader/pom.xml index 27250b99ef..1b5d4b7913 100644 --- a/code/framework/db-loader/pom.xml +++ b/code/framework/db-loader/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/deferred/pom.xml b/code/framework/deferred/pom.xml index 2518c3f746..f81f10cd98 100644 --- a/code/framework/deferred/pom.xml +++ b/code/framework/deferred/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/encryption/pom.xml b/code/framework/encryption/pom.xml index b41c6aa272..64f5744ae6 100644 --- a/code/framework/encryption/pom.xml +++ b/code/framework/encryption/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/engine/pom.xml b/code/framework/engine/pom.xml index 0f1dbb56ba..2b426f6a34 100644 --- a/code/framework/engine/pom.xml +++ b/code/framework/engine/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/eventing/pom.xml b/code/framework/eventing/pom.xml index a47b04795b..7b2bb95d0e 100644 --- a/code/framework/eventing/pom.xml +++ b/code/framework/eventing/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/events/pom.xml b/code/framework/events/pom.xml index 7df17213f3..891131a182 100644 --- a/code/framework/events/pom.xml +++ b/code/framework/events/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/extension-spring/pom.xml b/code/framework/extension-spring/pom.xml index c9fc8763e7..2ac3b20f77 100644 --- a/code/framework/extension-spring/pom.xml +++ b/code/framework/extension-spring/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/extension/pom.xml b/code/framework/extension/pom.xml index 6755d8aed1..d797540e88 100644 --- a/code/framework/extension/pom.xml +++ b/code/framework/extension/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/java-server/pom.xml b/code/framework/java-server/pom.xml index d62d399df3..3c8c0de1e4 100644 --- a/code/framework/java-server/pom.xml +++ b/code/framework/java-server/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/VolumeNativeWrappedResourceTest.java b/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/VolumeNativeWrappedResourceTest.java new file mode 100644 index 0000000000..1e900ee367 --- /dev/null +++ b/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/model/impl/VolumeNativeWrappedResourceTest.java @@ -0,0 +1,45 @@ +package io.github.ibuildthecloud.gdapi.model.impl; + +import static org.junit.Assert.*; + +import io.github.ibuildthecloud.gdapi.factory.SchemaFactory; +import io.github.ibuildthecloud.gdapi.factory.impl.SchemaFactoryImpl; +import io.github.ibuildthecloud.gdapi.id.IdFormatter; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; + +public class VolumeNativeWrappedResourceTest { + private final IdFormatter ids = new IdFormatter() { + public Object formatId(String type, Object id) { return id; } + public String parseId(String id) { return id; } + public IdFormatter withSchemaFactory(SchemaFactory factory) { return this; } + }; + + private Map render(boolean declared, Object actual, boolean present) { + SchemaImpl schema = new SchemaImpl(); + schema.setId("volume"); + if (declared) { + FieldImpl flag = new FieldImpl(); + flag.setType("boolean"); + flag.setDefault(Boolean.FALSE); + schema.getResourceFields().put("isNative", flag); + } + Map values = new HashMap(); + if (present) values.put("isNative", actual); + return new WrappedResource(ids, new SchemaFactoryImpl(), schema, null, values, null, "GET").getFields(); + } + + @Test + public void formatterRetainsTheActualServerTrueAndFalseClassification() { + assertEquals(Boolean.TRUE, render(true, Boolean.TRUE, true).get("isNative")); + assertEquals(Boolean.FALSE, render(true, Boolean.FALSE, true).get("isNative")); + } + + @Test + public void onlyAnExplicitSchemaContractCanProvideTheServerDefault() { + assertEquals(Boolean.FALSE, render(true, null, false).get("isNative")); + assertFalse(render(false, Boolean.FALSE, true).containsKey("isNative")); + assertFalse(render(false, Boolean.TRUE, true).containsKey("isNative")); + } +} diff --git a/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/validation/ValidationHandlerTest.java b/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/validation/ValidationHandlerTest.java index 5e54140b6a..c684dd3ecc 100644 --- a/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/validation/ValidationHandlerTest.java +++ b/code/framework/java-server/src/test/java/io/github/ibuildthecloud/gdapi/validation/ValidationHandlerTest.java @@ -18,6 +18,28 @@ public class ValidationHandlerTest { + @Test + public void clientCannotSetServerOwnedVolumeNativeClassification() { + SchemaImpl schema = new SchemaImpl(); + schema.setId("volume"); + FieldImpl flag = new FieldImpl(); + flag.setType("boolean"); + flag.setDefault(Boolean.FALSE); + schema.getResourceFields().put("isNative", flag); + ValidationHandler handler = new ValidationHandler(); + for (Object attempt : Arrays.asList(Boolean.TRUE, Boolean.FALSE, "true", null)) { + Map input = new HashMap(); + input.put("isNative", attempt); + ApiRequest request = new ApiRequest(null, null); + request.setRequestObject(input); + handler.validateOperationField(schema, request, true, new ValidationContext()); + assertEquals(Boolean.FALSE, RequestUtils.toMap(request.getRequestObject()).get("isNative")); + request.setRequestObject(input); + handler.validateOperationField(schema, request, false, new ValidationContext()); + assertFalse(RequestUtils.toMap(request.getRequestObject()).containsKey("isNative")); + } + } + @Test public void testNullableOption() { SchemaImpl schema = new SchemaImpl(); diff --git a/code/framework/jmx/pom.xml b/code/framework/jmx/pom.xml index 14ab721798..9e95ab3fa9 100644 --- a/code/framework/jmx/pom.xml +++ b/code/framework/jmx/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/jooq/pom.xml b/code/framework/jooq/pom.xml index 36ad46455f..e9c7a92c6a 100644 --- a/code/framework/jooq/pom.xml +++ b/code/framework/jooq/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/json/pom.xml b/code/framework/json/pom.xml index 04a9b71976..2a429b8355 100644 --- a/code/framework/json/pom.xml +++ b/code/framework/json/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/launcher/pom.xml b/code/framework/launcher/pom.xml index b16ae2594c..4f2be9512f 100644 --- a/code/framework/launcher/pom.xml +++ b/code/framework/launcher/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/lock/pom.xml b/code/framework/lock/pom.xml index ada4a7e888..b8e257b0c1 100644 --- a/code/framework/lock/pom.xml +++ b/code/framework/lock/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/logback/pom.xml b/code/framework/logback/pom.xml index 2ce4c92f5d..9dec7da6de 100644 --- a/code/framework/logback/pom.xml +++ b/code/framework/logback/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-meta-parent - 0.183.331 + 0.183.332 ../../meta-parent/pom.xml diff --git a/code/framework/managed-context/pom.xml b/code/framework/managed-context/pom.xml index 1fca0c1995..f658a4acf3 100644 --- a/code/framework/managed-context/pom.xml +++ b/code/framework/managed-context/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/metrics/pom.xml b/code/framework/metrics/pom.xml index b7df2c50c5..1d9a351daa 100644 --- a/code/framework/metrics/pom.xml +++ b/code/framework/metrics/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/module/pom.xml b/code/framework/module/pom.xml index 1099063daf..c2085d6e16 100644 --- a/code/framework/module/pom.xml +++ b/code/framework/module/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/object/pom.xml b/code/framework/object/pom.xml index 2653e8b7ad..562cca778a 100644 --- a/code/framework/object/pom.xml +++ b/code/framework/object/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/pool/pom.xml b/code/framework/pool/pom.xml index aee4a24a7b..e911c39c6d 100644 --- a/code/framework/pool/pom.xml +++ b/code/framework/pool/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/resource-monitor/pom.xml b/code/framework/resource-monitor/pom.xml index b4fde09d59..4d6e90e47f 100644 --- a/code/framework/resource-monitor/pom.xml +++ b/code/framework/resource-monitor/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/schema/pom.xml b/code/framework/schema/pom.xml index 810460708c..af23127f38 100644 --- a/code/framework/schema/pom.xml +++ b/code/framework/schema/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/schema/src/test/java/io/cattle/platform/schema/processor/VolumeNativeSchemaAuthorizationTest.java b/code/framework/schema/src/test/java/io/cattle/platform/schema/processor/VolumeNativeSchemaAuthorizationTest.java new file mode 100644 index 0000000000..56a341dc55 --- /dev/null +++ b/code/framework/schema/src/test/java/io/cattle/platform/schema/processor/VolumeNativeSchemaAuthorizationTest.java @@ -0,0 +1,126 @@ +package io.cattle.platform.schema.processor; + +import static org.junit.Assert.*; + +import io.cattle.platform.json.JacksonJsonMapper; +import io.cattle.platform.schema.processor.AuthOverlayPostProcessor; +import io.github.ibuildthecloud.gdapi.factory.SchemaFactory; +import io.github.ibuildthecloud.gdapi.factory.impl.SchemaFactoryImpl; +import io.github.ibuildthecloud.gdapi.model.Field; +import io.github.ibuildthecloud.gdapi.model.impl.FieldImpl; +import io.github.ibuildthecloud.gdapi.model.impl.SchemaImpl; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.Test; + +public class VolumeNativeSchemaAuthorizationTest { + @Test + public void currentRoleOverlaysExposeNativeClassificationWithoutGrantingMutation() throws Exception { + Path root = Paths.get("").toAbsolutePath(); + while (root != null && !Files.isRegularFile(root.resolve("resources/content/schema/user/user-auth.json"))) { + root = root.getParent(); + } + assertNotNull(root); + // MemberSchema inherits Project; its optional member-auth resource + // does not exist in this distribution. Use the actual shipped paths. + for (List overlays : Arrays.asList( + Arrays.asList("user/user-auth.json"), + Arrays.asList("user/user-auth.json", "admin/admin-auth.json"), + Arrays.asList("user/user-auth.json", "project/project-auth.json"), + Arrays.asList("user/user-auth.json", "project/project-auth.json", "owner/owner-auth.json"), + Arrays.asList("user/user-auth.json", "project/project-auth.json", "restricted-user/restricted-user.json"))) { + List resources = new ArrayList(); + for (String overlay : overlays) { + resources.add(root.resolve("resources/content/schema/" + overlay).toUri().toURL()); + } + AuthOverlayPostProcessor processor = new AuthOverlayPostProcessor(); + processor.setJsonMapper(new JacksonJsonMapper()); + processor.setResources(resources); + processor.init(); + SchemaImpl schema = new SchemaImpl(); + schema.setId("volume"); + FieldImpl flag = new FieldImpl(); + flag.setType("boolean"); + flag.setDefault(Boolean.FALSE); + schema.getResourceFields().put("isNative", flag); + assertSame(overlays.toString(), schema, processor.postProcessRegister(schema, null)); + processor.postProcess(schema, null); + Field field = schema.getResourceFields().get("isNative"); + assertNotNull(overlays.toString(), field); + assertFalse(overlays.toString(), field.isCreate()); + assertFalse(overlays.toString(), field.isUpdate()); + assertFalse(overlays.toString(), field.isReadOnCreateOnly()); + } + } + + @Test + public void readonlyPipelinePreservesCrudWhileRetainingServerOwnedNativeReadField() throws Exception { + Path root = Paths.get("").toAbsolutePath(); + while (root != null && !Files.isRegularFile(root.resolve("resources/content/schema/user/user-auth.json"))) { + root = root.getParent(); + } + assertNotNull(root); + SchemaFactory factory = new SchemaFactoryImpl(); + List originalCollectionMethods = null, originalResourceMethods = null; + for (boolean exposeNative : new boolean[] {false, true}) { + SchemaImpl schema = new SchemaImpl(); + schema.setId("volume"); + if (exposeNative) { + FieldImpl flag = new FieldImpl(); + flag.setType("boolean"); + flag.setDefault(Boolean.FALSE); + flag.setCreate(true); + flag.setUpdate(true); + schema.getResourceFields().put("isNative", flag); + } + AuthOverlayPostProcessor project = overlay(root, "user/user-auth.json", "project/project-auth.json"); + assertSame(schema, project.postProcessRegister(schema, factory)); + project.postProcess(schema, factory); + assertEquals(Arrays.asList("GET", "POST"), schema.getCollectionMethods()); + assertEquals(Arrays.asList("GET", "PUT", "DELETE"), schema.getResourceMethods()); + + // Match ReadOnlySchema: inherit Project, register NotWritable + // before read-user, then post-process in the same order. + NotWritablePostProcessor notWritable = new NotWritablePostProcessor(); + AuthOverlayPostProcessor readUser = overlay(root, "read-user/read-user.json"); + assertSame(schema, notWritable.postProcessRegister(schema, factory)); + assertSame(schema, readUser.postProcessRegister(schema, factory)); + notWritable.postProcess(schema, factory); + readUser.postProcess(schema, factory); + assertFalse(schema.isCreate()); + assertFalse(schema.isUpdate()); + assertFalse(schema.isDeletable()); + assertEquals(Arrays.asList("GET"), schema.getCollectionMethods()); + assertEquals(Arrays.asList("GET"), schema.getResourceMethods()); + if (!exposeNative) { + originalCollectionMethods = schema.getCollectionMethods(); + originalResourceMethods = schema.getResourceMethods(); + } else { + assertEquals(originalCollectionMethods, schema.getCollectionMethods()); + assertEquals(originalResourceMethods, schema.getResourceMethods()); + Field flag = schema.getResourceFields().get("isNative"); + assertNotNull(flag); + assertFalse(flag.isCreate()); + assertFalse(flag.isUpdate()); + assertFalse(flag.isReadOnCreateOnly()); + } + } + } + + private AuthOverlayPostProcessor overlay(Path root, String... paths) throws Exception { + List resources = new ArrayList(); + for (String path : paths) { + resources.add(root.resolve("resources/content/schema/" + path).toUri().toURL()); + } + AuthOverlayPostProcessor processor = new AuthOverlayPostProcessor(); + processor.setJsonMapper(new JacksonJsonMapper()); + processor.setResources(resources); + processor.init(); + return processor; + } +} diff --git a/code/framework/server/pom.xml b/code/framework/server/pom.xml index 556295f69b..d671c4d71a 100644 --- a/code/framework/server/pom.xml +++ b/code/framework/server/pom.xml @@ -4,7 +4,7 @@ cattle-meta-parent io.cattle - 0.183.331 + 0.183.332 ../../meta-parent/pom.xml diff --git a/code/framework/spring/pom.xml b/code/framework/spring/pom.xml index f756ee2a6a..51f38984c9 100644 --- a/code/framework/spring/pom.xml +++ b/code/framework/spring/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/system-task/pom.xml b/code/framework/system-task/pom.xml index e31718238b..a1c58d9647 100644 --- a/code/framework/system-task/pom.xml +++ b/code/framework/system-task/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/token/pom.xml b/code/framework/token/pom.xml index 91a7bf28ae..a2d0821c9b 100644 --- a/code/framework/token/pom.xml +++ b/code/framework/token/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/framework/utils/pom.xml b/code/framework/utils/pom.xml index 3060c5b2d0..981229acdb 100644 --- a/code/framework/utils/pom.xml +++ b/code/framework/utils/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/agent-instance/pom.xml b/code/iaas/agent-instance/pom.xml index 293ea42d59..fbfb2b60f9 100644 --- a/code/iaas/agent-instance/pom.xml +++ b/code/iaas/agent-instance/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/agent-server/pom.xml b/code/iaas/agent-server/pom.xml index 215aa1c114..520bc189c4 100644 --- a/code/iaas/agent-server/pom.xml +++ b/code/iaas/agent-server/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/agent/pom.xml b/code/iaas/agent/pom.xml index 433b38ad47..fa3d5a9245 100644 --- a/code/iaas/agent/pom.xml +++ b/code/iaas/agent/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/allocator/pom.xml b/code/iaas/allocator/pom.xml index b048299163..86143996c9 100644 --- a/code/iaas/allocator/pom.xml +++ b/code/iaas/allocator/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/api-logic/pom.xml b/code/iaas/api-logic/pom.xml index af921cef26..194690cd1f 100644 --- a/code/iaas/api-logic/pom.xml +++ b/code/iaas/api-logic/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/archaius-management/pom.xml b/code/iaas/archaius-management/pom.xml index 5a37cb351f..9da2859121 100644 --- a/code/iaas/archaius-management/pom.xml +++ b/code/iaas/archaius-management/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/auth-logic/pom.xml b/code/iaas/auth-logic/pom.xml index 6061116626..660d1f8e43 100644 --- a/code/iaas/auth-logic/pom.xml +++ b/code/iaas/auth-logic/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/bootstrap/pom.xml b/code/iaas/bootstrap/pom.xml index 6ac5a4fe9a..fadcd2e069 100644 --- a/code/iaas/bootstrap/pom.xml +++ b/code/iaas/bootstrap/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/config-item/api/pom.xml b/code/iaas/config-item/api/pom.xml index 7dc62a78b1..eb53a83dce 100644 --- a/code/iaas/config-item/api/pom.xml +++ b/code/iaas/config-item/api/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/iaas/config-item/common/pom.xml b/code/iaas/config-item/common/pom.xml index 8f35f99f0d..385fc91300 100644 --- a/code/iaas/config-item/common/pom.xml +++ b/code/iaas/config-item/common/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/iaas/config-item/server/pom.xml b/code/iaas/config-item/server/pom.xml index e35ef6e721..abd82f0f1e 100644 --- a/code/iaas/config-item/server/pom.xml +++ b/code/iaas/config-item/server/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/iaas/engine-jooq/pom.xml b/code/iaas/engine-jooq/pom.xml index 908b7a0908..69ebc8b2ba 100644 --- a/code/iaas/engine-jooq/pom.xml +++ b/code/iaas/engine-jooq/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/events/pom.xml b/code/iaas/events/pom.xml index ae60b2f90b..e6a34b1925 100644 --- a/code/iaas/events/pom.xml +++ b/code/iaas/events/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/external-handler/pom.xml b/code/iaas/external-handler/pom.xml index e9e540abbe..8661a46b8f 100644 --- a/code/iaas/external-handler/pom.xml +++ b/code/iaas/external-handler/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/ha/pom.xml b/code/iaas/ha/pom.xml index 8fa486cfa1..9161fcbf8b 100644 --- a/code/iaas/ha/pom.xml +++ b/code/iaas/ha/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/healthcheck/pom.xml b/code/iaas/healthcheck/pom.xml index b9e1c228fc..bca1be4570 100644 --- a/code/iaas/healthcheck/pom.xml +++ b/code/iaas/healthcheck/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/labels/pom.xml b/code/iaas/labels/pom.xml index 464cafefd2..17f885276f 100644 --- a/code/iaas/labels/pom.xml +++ b/code/iaas/labels/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/logic-common/pom.xml b/code/iaas/logic-common/pom.xml index 95dbc5f186..1183ffb0f1 100644 --- a/code/iaas/logic-common/pom.xml +++ b/code/iaas/logic-common/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/logic/pom.xml b/code/iaas/logic/pom.xml index e786ffceae..5f5f6e52e4 100644 --- a/code/iaas/logic/pom.xml +++ b/code/iaas/logic/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/metadata/pom.xml b/code/iaas/metadata/pom.xml index a8ec5ddcbd..7e7c916619 100644 --- a/code/iaas/metadata/pom.xml +++ b/code/iaas/metadata/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/model/pom.xml b/code/iaas/model/pom.xml index 069a10c775..3f2ff636f7 100644 --- a/code/iaas/model/pom.xml +++ b/code/iaas/model/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/resource-pool/pom.xml b/code/iaas/resource-pool/pom.xml index 552ca5cbbd..f350eceffe 100644 --- a/code/iaas/resource-pool/pom.xml +++ b/code/iaas/resource-pool/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/service-discovery/api/pom.xml b/code/iaas/service-discovery/api/pom.xml index caa7501974..e810e41f68 100644 --- a/code/iaas/service-discovery/api/pom.xml +++ b/code/iaas/service-discovery/api/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/iaas/service-discovery/server/pom.xml b/code/iaas/service-discovery/server/pom.xml index 2f9929a992..8b21b223e8 100644 --- a/code/iaas/service-discovery/server/pom.xml +++ b/code/iaas/service-discovery/server/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/iaas/ssh-common/pom.xml b/code/iaas/ssh-common/pom.xml index 96f87e9e0d..3755e1f488 100644 --- a/code/iaas/ssh-common/pom.xml +++ b/code/iaas/ssh-common/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/storage-service/pom.xml b/code/iaas/storage-service/pom.xml index 3959cca830..a18dd3bd70 100644 --- a/code/iaas/storage-service/pom.xml +++ b/code/iaas/storage-service/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/iaas/task-jooq/pom.xml b/code/iaas/task-jooq/pom.xml index c4ab677c51..c41976cef6 100644 --- a/code/iaas/task-jooq/pom.xml +++ b/code/iaas/task-jooq/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/implementation/activity-log/pom.xml b/code/implementation/activity-log/pom.xml index 47cc4346de..2806130e00 100644 --- a/code/implementation/activity-log/pom.xml +++ b/code/implementation/activity-log/pom.xml @@ -5,7 +5,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/implementation/agent-instance-impl/pom.xml b/code/implementation/agent-instance-impl/pom.xml index d99f753129..c708dc8149 100644 --- a/code/implementation/agent-instance-impl/pom.xml +++ b/code/implementation/agent-instance-impl/pom.xml @@ -3,7 +3,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml cattle-agent-instance-impl diff --git a/code/implementation/docker/api/pom.xml b/code/implementation/docker/api/pom.xml index 224a40cebb..939dcf286e 100644 --- a/code/implementation/docker/api/pom.xml +++ b/code/implementation/docker/api/pom.xml @@ -5,7 +5,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/implementation/docker/common/pom.xml b/code/implementation/docker/common/pom.xml index c4e878f233..e10c10dd15 100644 --- a/code/implementation/docker/common/pom.xml +++ b/code/implementation/docker/common/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/implementation/docker/compute/pom.xml b/code/implementation/docker/compute/pom.xml index 6d9c15495d..cbf39e750e 100644 --- a/code/implementation/docker/compute/pom.xml +++ b/code/implementation/docker/compute/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/implementation/docker/machine/pom.xml b/code/implementation/docker/machine/pom.xml index 4bc76f5a31..8cecef902c 100644 --- a/code/implementation/docker/machine/pom.xml +++ b/code/implementation/docker/machine/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/implementation/docker/storage/pom.xml b/code/implementation/docker/storage/pom.xml index 466ab32b53..bf15099056 100644 --- a/code/implementation/docker/storage/pom.xml +++ b/code/implementation/docker/storage/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml @@ -21,12 +21,12 @@ io.cattle cattle-docker-common - 0.183.331 + 0.183.332 io.cattle cattle-iaas-allocator - 0.183.331 + 0.183.332 diff --git a/code/implementation/extension-api/pom.xml b/code/implementation/extension-api/pom.xml index e66ccc27e0..f324bddbf5 100644 --- a/code/implementation/extension-api/pom.xml +++ b/code/implementation/extension-api/pom.xml @@ -3,7 +3,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml cattle-extension-api diff --git a/code/implementation/hazelcast/common/pom.xml b/code/implementation/hazelcast/common/pom.xml index 4048299467..e2e7433263 100644 --- a/code/implementation/hazelcast/common/pom.xml +++ b/code/implementation/hazelcast/common/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/implementation/hazelcast/eventing/pom.xml b/code/implementation/hazelcast/eventing/pom.xml index 137f795147..fae72b111f 100644 --- a/code/implementation/hazelcast/eventing/pom.xml +++ b/code/implementation/hazelcast/eventing/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/implementation/hazelcast/lock/pom.xml b/code/implementation/hazelcast/lock/pom.xml index 50ffd560d8..c78afd19c5 100644 --- a/code/implementation/hazelcast/lock/pom.xml +++ b/code/implementation/hazelcast/lock/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/implementation/host-api/pom.xml b/code/implementation/host-api/pom.xml index 3977d37a26..c6b446ada6 100644 --- a/code/implementation/host-api/pom.xml +++ b/code/implementation/host-api/pom.xml @@ -5,7 +5,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/implementation/host-stats/pom.xml b/code/implementation/host-stats/pom.xml index 053fae51db..23c95a6e6e 100644 --- a/code/implementation/host-stats/pom.xml +++ b/code/implementation/host-stats/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/implementation/register/pom.xml b/code/implementation/register/pom.xml index eeeda94ede..117556f4f2 100644 --- a/code/implementation/register/pom.xml +++ b/code/implementation/register/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/implementation/sample-setup/pom.xml b/code/implementation/sample-setup/pom.xml index 276fc3983f..16b7cbad39 100644 --- a/code/implementation/sample-setup/pom.xml +++ b/code/implementation/sample-setup/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/implementation/settings-api/pom.xml b/code/implementation/settings-api/pom.xml index 31d0efac2e..ba8f5e2b5f 100644 --- a/code/implementation/settings-api/pom.xml +++ b/code/implementation/settings-api/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/implementation/simulator/agent-connection/pom.xml b/code/implementation/simulator/agent-connection/pom.xml index 126efbd99b..5cdf223aee 100644 --- a/code/implementation/simulator/agent-connection/pom.xml +++ b/code/implementation/simulator/agent-connection/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/implementation/simulator/storage/pom.xml b/code/implementation/simulator/storage/pom.xml index c468a7ffbd..217938ad55 100644 --- a/code/implementation/simulator/storage/pom.xml +++ b/code/implementation/simulator/storage/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../../parent/pom.xml diff --git a/code/implementation/system-stack/pom.xml b/code/implementation/system-stack/pom.xml index 8d65965698..9803ec614f 100644 --- a/code/implementation/system-stack/pom.xml +++ b/code/implementation/system-stack/pom.xml @@ -5,7 +5,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/implementation/vm/pom.xml b/code/implementation/vm/pom.xml index f76934b280..ded78f922e 100644 --- a/code/implementation/vm/pom.xml +++ b/code/implementation/vm/pom.xml @@ -3,7 +3,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml cattle-vm diff --git a/code/meta-parent/pom.xml b/code/meta-parent/pom.xml index 9e06cccd5e..fcb8e2256a 100644 --- a/code/meta-parent/pom.xml +++ b/code/meta-parent/pom.xml @@ -9,7 +9,7 @@ 4.0.0 io.cattle cattle-meta-parent - 0.183.331 + 0.183.332 pom PastureStack Orchestration Engine Compatibility orchestration engine for the PastureStack server. diff --git a/code/packaging/app-config/pom.xml b/code/packaging/app-config/pom.xml index 4caf28c79a..9d9ea0f164 100644 --- a/code/packaging/app-config/pom.xml +++ b/code/packaging/app-config/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml jar diff --git a/code/packaging/app/pom.xml b/code/packaging/app/pom.xml index 34c14cdad1..0ce5ed47e0 100644 --- a/code/packaging/app/pom.xml +++ b/code/packaging/app/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml war diff --git a/code/packaging/bundle/pom.xml b/code/packaging/bundle/pom.xml index 1707317bf0..9cb6c78484 100644 --- a/code/packaging/bundle/pom.xml +++ b/code/packaging/bundle/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/packaging/dev/pom.xml b/code/packaging/dev/pom.xml index 3f989cd99f..e478f5e0c9 100644 --- a/code/packaging/dev/pom.xml +++ b/code/packaging/dev/pom.xml @@ -4,7 +4,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/packaging/meta/pom.xml b/code/packaging/meta/pom.xml index e9c5a9a2d9..a3479a6f67 100644 --- a/code/packaging/meta/pom.xml +++ b/code/packaging/meta/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../../parent/pom.xml diff --git a/code/parent/pom.xml b/code/parent/pom.xml index 8d9046a7ac..c15fcf2646 100644 --- a/code/parent/pom.xml +++ b/code/parent/pom.xml @@ -5,7 +5,7 @@ io.cattle cattle-meta-parent ../meta-parent/pom.xml - 0.183.331 + 0.183.332 pom diff --git a/docs/releases/orchestration-engine-0.183.332.md b/docs/releases/orchestration-engine-0.183.332.md new file mode 100644 index 0000000000..2ff1995767 --- /dev/null +++ b/docs/releases/orchestration-engine-0.183.332.md @@ -0,0 +1,47 @@ +# Orchestration Engine 0.183.332 — candidate + +## Root cause and change + +The Web Console unallocated-volume list requires an explicit `isNative=false` +classification. The current API role overlay removes `isNative`, and frozen v1 +role schemas also omit it. An absent flag cannot safely be interpreted as false. + +This candidate adds `volume.isNative:r` to the existing user authorization +overlay and narrowly supplements the missing field in `FileSchemaFactory`. +The field remains server-owned and read-only. Existing Volume methods, actions, +other fields, account scoping and role restrictions are not changed. Stored +true/false values remain authoritative; the existing nonnullable boolean default +is applied only by the server's declared schema. No frontend fallback, data +migration, runtime patch or proxy change is introduced. + +## Verification completed + +The targeted Maven reactor passed 18 tests with zero failures, errors or skips, +including six new tests covering: + +- Packaged v1 owner, member, readonly, restricted, user and admin schemas; + only the missing native field is added, preserving other field serialization, + methods and complete resource/collection action serialization. +- Shipped v2 user/admin/project/owner/readonly/restricted overlays, with no + create/update permission on the native flag, including the actual readonly + `Project → NotWritable → read-user` sequence with unchanged GET-only methods. +- Formatter preservation of true/false, the declared server default and no + undeclared boolean leakage. +- Client POST/PUT attempts to change classification: client values are excluded; + creation uses only the server default. + +The release workflow additionally requires these named regressions to pass. + +## Pending acceptance + +This is not yet a published artifact or a complete Volume lifecycle pass. +Formal immutable component readback, Server packaging and actual browser +create/list/edit/cancel/reload/delete and role denials remain required. + +## Upgrade and rollback + +No persisted data or role membership migration is needed. Preserve existing +deployment environment, mounts, restart policy and authentication configuration. +Use an immutable newly published Server image only after the component gates +pass; do not overwrite previous tags. Rolling back the component restores the +old missing-field response contract and can hide unallocated volumes again. diff --git a/pom.xml b/pom.xml index ce5b15110c..238134b00a 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ io.cattle cattle-parent - 0.183.331 + 0.183.332 code/parent/pom.xml cattle diff --git a/resources/content/schema/user/user-auth.json b/resources/content/schema/user/user-auth.json index f44d643fb8..0826ceed2b 100644 --- a/resources/content/schema/user/user-auth.json +++ b/resources/content/schema/user/user-auth.json @@ -699,6 +699,7 @@ "volume.imageId" : "r", "volume.instanceId" : "r", "volume.isHostPath" : "r", + "volume.isNative" : "r", "volume.uri" : "r", "volume.driver": "cr", "volume.driverOpts": "cru", diff --git a/resources/pom.xml b/resources/pom.xml index 1cd77e9580..6568faff64 100644 --- a/resources/pom.xml +++ b/resources/pom.xml @@ -4,7 +4,7 @@ cattle-parent io.cattle - 0.183.331 + 0.183.332 ../code/parent/pom.xml diff --git a/scripts/build b/scripts/build index 420f230b11..fd96e0e1aa 100755 --- a/scripts/build +++ b/scripts/build @@ -16,7 +16,7 @@ fi SOURCE_REVISION=${SOURCE_REVISION:-$(git rev-parse HEAD)} SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH:-$(git show -s --format=%ct HEAD)} -ENGINE_VERSION=${ENGINE_VERSION:-0.183.331} +ENGINE_VERSION=${ENGINE_VERSION:-0.183.332} case "$SOURCE_REVISION" in ''|*[!0-9a-f]*) diff --git a/scripts/check-pasturestack-source b/scripts/check-pasturestack-source index c788ce7f76..fa4ba9ceec 100755 --- a/scripts/check-pasturestack-source +++ b/scripts/check-pasturestack-source @@ -51,7 +51,7 @@ fi project_version=$(sed -n 's/^[[:space:]]*\([^<]*\)<\/version>[[:space:]]*$/\1/p' code/meta-parent/pom.xml | head -n 1) [[ "$project_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || fail non_numeric_project_version -require_line code/meta-parent/pom.xml ' 0.183.331' +require_line code/meta-parent/pom.xml ' 0.183.332' require_line code/meta-parent/pom.xml ' 2.3.35' require_line "$iaas_api_defaults" 'auth.service.external.id.types=github_user,github_org,github_team,shibboleth_user,shibboleth_group,ldap_user,ldap_group,oidc_user,oidc_group' require_line code/meta-parent/pom.xml ' https://github.com/PastureStack/orchestration-engine' @@ -411,9 +411,11 @@ if grep -E '=(https?://|ghcr\.io/)' "$settings" \ fail non_pasturestack_runtime_source fi +require_line resources/content/schema/user/user-auth.json ' "volume.isNative" : "r",' +require_line code/framework/api/src/main/java/io/cattle/platform/api/schema/FileSchemaFactory.java ' mergeVolumeNativeReadField(schema, coreSchema);' require_line README.md 'PastureStack is an independent community effort to preserve, audit, and' require_line README.md 'modernize the Rancher 1.6 ecosystem. It is not affiliated with or endorsed' require_line README.md 'by Rancher Labs or SUSE.' require_line ORIGIN.md '- Preserved upstream boundary: `82d154a53f4089fecfb9f320caad826bb4f6055f`' -printf 'PASTURESTACK_SOURCE_GATE_OK version=0.183.331 runtime_sources=github_release images=digest_pinned ubuntu=26.04 ubuntu_snapshot=20260826T000000Z jdk=25.0.4 maven=3.9.16 patched_hazelcast=5.7.5 docker_cli=29.7.2 docker_host_29_8_0=exact credential_secret_capacity=mediumtext port_preflight=authoritative volume_preflight=runtime_resolution_aligned volume_preflight_project_schema=authorized volume_preflight_type_set=registered v1_hardware_schema=container-and-launchConfig network_driver_rollback=launch-config-restored stack_driver_rollback=child-launch-config-restored auth_token_session_binding=authorized-create-only auth_token_transport=bare-or-bearer-normalized auth_token_frozen_v1_schema=base-superadmin-token oidc_external_types=validated-before-mutation-owned-stable-account oidc_account_activation=sync-before-mfa oidc_v1_project_member_schema=core-options-merged-scoped oidc_identity_link_owner=explicit-and-verified legacy_token_link_repair=exact-match-only oidc_required_local_recovery=active-admin-only default_project=shared-idempotent-role-preserving,atomic-identity-set oidc_restricted_project_membership=stable-account-aware-required-allowlist-only mfa_policy_confirmation=actor-purpose-digest-single-use auth_config_proxy_identity=caller-platform-credential project_member_collection_acl=requested-project-checked-before-load project_template_v1_public=readonly-frozen-field-merged network_purge=retry-removing dev_artifact=forbidden\n' +printf 'PASTURESTACK_SOURCE_GATE_OK version=0.183.332 runtime_sources=github_release images=digest_pinned ubuntu=26.04 ubuntu_snapshot=20260826T000000Z jdk=25.0.4 maven=3.9.16 patched_hazelcast=5.7.5 docker_cli=29.7.2 docker_host_29_8_0=exact credential_secret_capacity=mediumtext port_preflight=authoritative volume_preflight=runtime_resolution_aligned volume_preflight_project_schema=authorized volume_preflight_type_set=registered v1_hardware_schema=container-and-launchConfig network_driver_rollback=launch-config-restored stack_driver_rollback=child-launch-config-restored auth_token_session_binding=authorized-create-only auth_token_transport=bare-or-bearer-normalized auth_token_frozen_v1_schema=base-superadmin-token oidc_external_types=validated-before-mutation-owned-stable-account oidc_account_activation=sync-before-mfa oidc_v1_project_member_schema=core-options-merged-scoped oidc_identity_link_owner=explicit-and-verified legacy_token_link_repair=exact-match-only oidc_required_local_recovery=active-admin-only default_project=shared-idempotent-role-preserving,atomic-identity-set oidc_restricted_project_membership=stable-account-aware-required-allowlist-only mfa_policy_confirmation=actor-purpose-digest-single-use auth_config_proxy_identity=caller-platform-credential project_member_collection_acl=requested-project-checked-before-load project_template_v1_public=readonly-frozen-field-merged network_purge=retry-removing dev_artifact=forbidden\n' diff --git a/scripts/check-release-artifact b/scripts/check-release-artifact index 064403bf47..742fb4d6d0 100755 --- a/scripts/check-release-artifact +++ b/scripts/check-release-artifact @@ -4,7 +4,7 @@ set -euo pipefail cd "$(dirname "$0")/.." artifact=${1:-dist/artifacts/cattle.jar} -expected_version=${EXPECTED_ENGINE_VERSION:-0.183.331} +expected_version=${EXPECTED_ENGINE_VERSION:-0.183.332} test -f "$artifact" artifact=$(realpath "$artifact")