Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/security-release-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,62 @@ jobs:
cp dist/version evidence/engine-version.txt
sha256sum dist/artifacts/cattle.jar > evidence/cattle.jar.sha256

- name: Retain executed unit cases without properties or log content
shell: bash
run: |
set -euo pipefail
python3 - <<'PY'
import json
from pathlib import Path
import xml.etree.ElementTree as ET

required = {
'io.github.ibuildthecloud.gdapi.request.handler.BodyParserRequestHandlerTest': {
'mergeMapKeepsRequestParamsAndLetsBodyOverride',
'mergeListRecursivelyMergesAllowedMapItems',
'parsesObjectUnicodeAndAdditionalFieldsWithRealMapper',
'parsesListWithRealMapperAndMergesObjectItems',
'typedMapperIgnoresUnknownFieldsAndRoundTripsUnicode',
'malformedJsonReturnsInvalidBodyContentBadRequest',
},
'io.cattle.platform.iaas.api.auth.mfa.WebAuthnConfigurationTest': {
'acceptsExactHttpsOriginAndRelyingParty',
'acceptsHttpOnlyForLoopbackDevelopment',
'rejectsInsecureLanOrigin', 'rejectsUnrelatedRelyingParty',
'rejectsPublicSuffixAsRelyingParty',
'objectConverterJsonRoundTripsNormalWebAuthnValues',
'objectConverterCborRoundTripsNormalValuesAndBinaryData',
'credentialDataStorageRoundTripPreservesPublicKeyAndCredentialId',
},
}
suites = []
observed = {}
for path in sorted(Path('code').glob('**/target/surefire-reports/TEST-*.xml')):
root = ET.parse(path).getroot()
cases = []
for case in root.findall('testcase'):
outcomes = [name for name in ('failure', 'error', 'skipped') if case.find(name) is not None]
record = {'class': case.get('classname'), 'name': case.get('name'),
'status': outcomes[0] if outcomes else 'passed'}
cases.append(record)
if record['class'] in required:
key = (record['class'], record['name'])
assert key not in observed, ('duplicate required case', key)
observed[key] = record['status']
counts = {name: int(root.get(name, '0')) for name in ('tests', 'failures', 'errors', 'skipped')}
assert counts['tests'] == len(cases), ('report case count', str(path))
assert counts['failures'] == counts['errors'] == 0, ('failed unit suite', str(path))
suites.append({'report': path.as_posix(), 'counts': counts, 'cases': cases})
assert suites, 'No executed Surefire unit reports'
expected = {(name, case) for name, cases in required.items() for case in cases}
assert set(observed) == expected and set(observed.values()) == {'passed'}, 'Required cases missing, skipped or failed'
summary = {'source': Path('evidence/source-revision.txt').read_text().strip(),
'suiteCount': len(suites), 'totals': {name: sum(s['counts'][name] for s in suites)
for name in ('tests', 'failures', 'errors', 'skipped')}, 'suites': suites}
Path('evidence/unit-test-results.json').write_text(json.dumps(summary, sort_keys=True, indent=2) + '\n')
print('UNIT_CASE_EVIDENCE_OK', summary['suiteCount'], summary['totals'])
PY

- name: Record resolved build inputs
shell: bash
run: |
Expand Down
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ and verifies its pinned digest and dependency metadata before installing it
into the build-local Maven repository. See
[`third-party/HAZELCAST.md`](third-party/HAZELCAST.md) for provenance.

## Unreleased 0.183.328 candidate

The source candidate updates platform Jackson to `2.22.3` and the isolated
WebAuthn/logging Jackson line to `3.2.3`, with patchless annotations remaining
`2.22`. These are the official patched versions for CVE-2026-91776 and
CVE-2026-91777; see the [candidate note](docs/releases/orchestration-engine-0.183.328.md).
The candidate pins the corresponding officially published
[`distributed-cache-runtime` `5.7.5` artifact](https://github.com/PastureStack/distributed-cache-runtime/releases/tag/v5.7.5),
because `5.7.4` embeds both older Jackson versions. The actual release JAR,
source commit, checksum, and asset ID were read back and verified; see the
[Cache provenance](third-party/HAZELCAST.md). Engine328 has not yet been built
or published, and its seven new Java regression cases have not yet been
compiled or executed. Cache's producer checks are not Engine validation.
No Engine328 artifact, CI PASS, Server496 digest, or deployment is claimed.
The published 327 provenance above remains historical and unchanged.

## Build and validation

Before publishing an Engine artifact or a Server image, run the complete
Expand All @@ -64,7 +80,7 @@ bash scripts/check-cattle-jdk25-full-package
After the gate passes, package and check the release artifact:

```sh
ENGINE_VERSION=0.183.327 bash scripts/build --release
ENGINE_VERSION=0.183.328 bash scripts/build --release
bash scripts/check-release-artifact dist/artifacts/cattle.jar
```

Expand Down
2 changes: 1 addition & 1 deletion code/framework/api-pub-sub-jetty/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/api-pub-sub/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>cattle-parent</artifactId>
<groupId>io.cattle</groupId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/archaius/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-meta-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../meta-parent/pom.xml</relativePath>
</parent>
</project>
2 changes: 1 addition & 1 deletion code/framework/async/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/auditing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>cattle-parent</artifactId>
<groupId>io.cattle</groupId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion code/framework/db-loader/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/deferred/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/encryption/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/engine/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/eventing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/events/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/extension-spring/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>cattle-parent</artifactId>
<groupId>io.cattle</groupId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/extension/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>cattle-parent</artifactId>
<groupId>io.cattle</groupId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/java-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;

import io.github.ibuildthecloud.gdapi.exception.ClientVisibleException;
import io.github.ibuildthecloud.gdapi.json.JacksonMapper;
import io.github.ibuildthecloud.gdapi.request.ApiRequest;
import io.github.ibuildthecloud.gdapi.util.ResponseCodes;
import io.github.ibuildthecloud.gdapi.validation.ValidationErrorCodes;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
Expand All @@ -17,11 +26,15 @@ public class BodyParserRequestHandlerTest {

BodyParserRequestHandler handler;
ApiRequest request;
JacksonMapper mapper;

@Before
public void setUp() {
handler = new BodyParserRequestHandler();
handler.init();
mapper = new JacksonMapper();
mapper.init();
handler.setJsonMarshaller(mapper);

request = new ApiRequest(null, null);
Map<String, Object> params = new HashMap<String, Object>();
Expand Down Expand Up @@ -58,4 +71,77 @@ public void mergeListRecursivelyMergesAllowedMapItems() {
assertEquals("second", ((Map<?, ?>)result.get(1)).get("name"));
assertFalse(result.contains("ignored"));
}

@Test
public void parsesObjectUnicodeAndAdditionalFieldsWithRealMapper() throws Exception {
ApiRequest bodyRequest = jsonRequest("{\"name\":\"繁體中文/測試🙂\","
+ "\"additionalField\":{\"enabled\":true,\"labels\":[\"甲\",\"乙\"]}}");

handler.handle(bodyRequest);

Map<?, ?> result = (Map<?, ?>)bodyRequest.getRequestObject();
assertEquals("繁體中文/測試🙂", result.get("name"));
assertEquals("query-value", result.get("queryOnly"));
Map<?, ?> additional = (Map<?, ?>)result.get("additionalField");
assertEquals(Boolean.TRUE, additional.get("enabled"));
assertEquals(Arrays.asList("甲", "乙"), additional.get("labels"));
}

@Test
public void parsesListWithRealMapperAndMergesObjectItems() throws Exception {
ApiRequest bodyRequest = jsonRequest("[{\"name\":\"first\"},\"ignored\","
+ "{\"name\":\"second\",\"count\":2}]");

handler.handle(bodyRequest);

List<?> result = (List<?>)bodyRequest.getRequestObject();
assertEquals(2, result.size());
assertEquals("first", ((Map<?, ?>)result.get(0)).get("name"));
assertEquals("second", ((Map<?, ?>)result.get(1)).get("name"));
assertEquals(2, ((Map<?, ?>)result.get(1)).get("count"));
assertEquals("query-value", ((Map<?, ?>)result.get(1)).get("queryOnly"));
}

@Test
public void typedMapperIgnoresUnknownFieldsAndRoundTripsUnicode() throws Exception {
NameOnly value = mapper.readValue("{\"name\":\"名稱/✓\",\"futureField\":true}"
.getBytes(StandardCharsets.UTF_8), NameOnly.class);
assertEquals("名稱/✓", value.name);

ByteArrayOutputStream output = new ByteArrayOutputStream();
mapper.writeValue(output, value);
Map<?, ?> result = mapper.readValue(output.toByteArray(), Map.class);
assertEquals("名稱/✓", result.get("name"));
assertFalse(result.containsKey("futureField"));
}

@Test
public void malformedJsonReturnsInvalidBodyContentBadRequest() throws Exception {
for (String malformed : Arrays.asList("{\"name\":", "[{\"name\":\"broken\"}")) {
try {
handler.handle(jsonRequest(malformed));
fail("Malformed JSON must not be accepted");
} catch (ClientVisibleException error) {
assertEquals(ResponseCodes.BAD_REQUEST, error.getStatus());
assertEquals(ValidationErrorCodes.INVALID_BODY_CONTENT, error.getCode());
}
}
}

private ApiRequest jsonRequest(String json) {
final byte[] content = json.getBytes(StandardCharsets.UTF_8);
ApiRequest bodyRequest = new ApiRequest(null, null) {
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(content);
}
};
bodyRequest.setMethod("POST");
bodyRequest.setRequestParams(request.getRequestParams());
return bodyRequest;
}

public static class NameOnly {
public String name;
}
}
2 changes: 1 addition & 1 deletion code/framework/jmx/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/jooq/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/json/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/launcher/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/lock/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
2 changes: 1 addition & 1 deletion code/framework/logback/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cattle</groupId>
<artifactId>cattle-meta-parent</artifactId>
<version>0.183.327</version>
<version>0.183.328</version>
<relativePath>../../meta-parent/pom.xml</relativePath>
</parent>
<dependencies>
Expand Down
Loading
Loading