Merge pull request #130 from confio/builder-tests

Add and test isValidBuilder
This commit is contained in:
merge-when-green[bot] 2020-03-02 11:26:57 +00:00 committed by GitHub
commit 1804a0b679
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 1 deletions

View File

@ -0,0 +1,63 @@
import { isValidBuilder } from "./builder";
describe("builder", () => {
describe("isValidBuilder", () => {
// Valid cases
it("returns true for simple examples", () => {
expect(isValidBuilder("myorg/super-optimizer:0.1.2")).toEqual(true);
expect(isValidBuilder("myorg/super-optimizer:42")).toEqual(true);
});
it("supports images with multi level names", () => {
expect(isValidBuilder("myorg/department-x/office-y/technology-z/super-optimizer:0.1.2")).toEqual(true);
});
it("returns true for tags with lower and upper chars", () => {
expect(isValidBuilder("myorg/super-optimizer:0.1.2-alpha")).toEqual(true);
expect(isValidBuilder("myorg/super-optimizer:0.1.2-Alpha")).toEqual(true);
});
// Invalid cases
it("returns false for missing or empty tag", () => {
expect(isValidBuilder("myorg/super-optimizer")).toEqual(false);
expect(isValidBuilder("myorg/super-optimizer:")).toEqual(false);
});
it("returns false for name components starting or ending with a separator", () => {
expect(isValidBuilder(".myorg/super-optimizer:42")).toEqual(false);
expect(isValidBuilder("-myorg/super-optimizer:42")).toEqual(false);
expect(isValidBuilder("_myorg/super-optimizer:42")).toEqual(false);
expect(isValidBuilder("myorg./super-optimizer:42")).toEqual(false);
expect(isValidBuilder("myorg-/super-optimizer:42")).toEqual(false);
expect(isValidBuilder("myorg_/super-optimizer:42")).toEqual(false);
expect(isValidBuilder("myorg/.super-optimizer:42")).toEqual(false);
expect(isValidBuilder("myorg/-super-optimizer:42")).toEqual(false);
expect(isValidBuilder("myorg/_super-optimizer:42")).toEqual(false);
expect(isValidBuilder("myorg/super-optimizer.:42")).toEqual(false);
expect(isValidBuilder("myorg/super-optimizer-:42")).toEqual(false);
expect(isValidBuilder("myorg/super-optimizer_:42")).toEqual(false);
});
it("returns false for upper case character in name component", () => {
expect(isValidBuilder("mYorg/super-optimizer:42")).toEqual(false);
expect(isValidBuilder("myorg/super-Optimizer:42")).toEqual(false);
});
it("returns false for long images", () => {
expect(
isValidBuilder(
"myorgisnicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenicenice/super-optimizer:42",
),
).toEqual(false);
});
it("returns false for images with no organization", () => {
// Those are valid dockerhub images from https://hub.docker.com/_/ubuntu and https://hub.docker.com/_/rust
// but not valid in the context of CosmWasm Verify
expect(isValidBuilder("ubuntu:xenial-20200212")).toEqual(false);
expect(isValidBuilder("rust:1.40.0")).toEqual(false);
});
});
});

View File

@ -0,0 +1,20 @@
// A docker image regexp. We remove support for non-standard registries for simplicity.
// https://docs.docker.com/engine/reference/commandline/tag/#extended-description
//
// An image name is made up of slash-separated name components (optionally prefixed by a registry hostname).
// Name components may contain lowercase characters, digits and separators.
// A separator is defined as a period, one or two underscores, or one or more dashes. A name component may not start or end with a separator.
//
// A tag name must be valid ASCII and may contain lowercase and uppercase letters, digits, underscores, periods and dashes.
// A tag name may not start with a period or a dash and may contain a maximum of 128 characters.
const dockerImagePattern = new RegExp(
"^[a-z0-9][a-z0-9._-]*[a-z0-9](/[a-z0-9][a-z0-9._-]*[a-z0-9])+:[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127}$",
);
/** Max length in bytes/characters (regexp enforces all ASCII, even if that is not required by the standard) */
const builderMaxLength = 128;
export function isValidBuilder(builder: string): boolean {
if (builder.length > builderMaxLength) return false;
return !!builder.match(dockerImagePattern);
}

View File

@ -2,6 +2,7 @@ import { Sha256 } from "@iov/crypto";
import { Encoding } from "@iov/encoding";
import pako from "pako";
import { isValidBuilder } from "./builder";
import { CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient";
import { makeSignBytes } from "./encoding";
import { findAttribute, Log } from "./logs";
@ -32,6 +33,15 @@ function singleAmount(amount: number, denom: string): readonly Coin[] {
return [{ amount: amount.toString(), denom: denom }];
}
function prepareBuilder(buider: string | undefined): string {
if (buider === undefined) {
return ""; // normalization needed by backend
} else {
if (!isValidBuilder(buider)) throw new Error("The builder (Docker Hub image with tag) is not valid");
return buider;
}
}
const defaultFees: FeeTable = {
upload: {
amount: singleAmount(25000, "ucosm"),
@ -105,7 +115,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
/** Uploads code and returns a receipt, including the code ID */
public async upload(wasmCode: Uint8Array, meta: UploadMeta = {}, memo = ""): Promise<UploadReceipt> {
const source = meta.source || "";
const builder = meta.builder || "";
const builder = prepareBuilder(meta.builder);
const compressed = pako.gzip(wasmCode, { level: 9 });
const storeCodeMsg: MsgStoreCode = {

1
packages/sdk/types/builder.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export declare function isValidBuilder(builder: string): boolean;