diff --git a/apps/console/src/components/mint-node-scep-challenge-dialog.test.tsx b/apps/console/src/components/mint-node-scep-challenge-dialog.test.tsx new file mode 100644 index 0000000..c244781 --- /dev/null +++ b/apps/console/src/components/mint-node-scep-challenge-dialog.test.tsx @@ -0,0 +1,93 @@ +/* +Copyright The CryptOS Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +import { MintNodeScepChallengeDialog } from "@/components/mint-node-scep-challenge-dialog"; +import { expectNoA11yViolations } from "@/test/axe"; + +const mintNodeScepChallenge = vi.fn(); +vi.mock("@/lib/node-scep-challenges", () => ({ + mintNodeScepChallenge: (...a: unknown[]) => mintNodeScepChallenge(...a), +})); + +const mintButton = () => screen.getByRole("button", { name: /^mint challenge$/i }); + +const renderDialog = () => + render( + , + ); + +describe("MintNodeScepChallengeDialog", () => { + beforeEach(() => { + mintNodeScepChallenge.mockReset(); + mintNodeScepChallenge.mockResolvedValue({ + challenge: { + boundNames: [], + createdAt: "", + createdByCn: "", + expiresAt: "", + id: "ch-1", + profile: "network-device", + }, + challengePassword: "one-time-password-123", + }); + }); + + it("has no axe violations before minting", async () => { + renderDialog(); + await expectNoA11yViolations(document.body); + }); + + it("mints with the entered profile, ttl and bound names, then shows the password once", async () => { + const onMinted = vi.fn(); + render( + , + ); + + fireEvent.change(screen.getByLabelText(/^profile$/i), { target: { value: "network-device" } }); + fireEvent.change(screen.getByLabelText(/ttl/i), { target: { value: "7200" } }); + fireEvent.change(screen.getByLabelText(/bound names/i), { + target: { value: "switch-1.example.org, 10.0.0.5" }, + }); + fireEvent.click(mintButton()); + + await waitFor(() => + expect(mintNodeScepChallenge).toHaveBeenCalledWith("acme-edge-07", { + boundNames: ["switch-1.example.org", "10.0.0.5"], + profile: "network-device", + ttlSeconds: 7200, + }), + ); + expect(await screen.findByText("one-time-password-123")).toBeInTheDocument(); + expect(onMinted).toHaveBeenCalled(); + }); + + it("has no axe violations after minting (shown-once secret)", async () => { + renderDialog(); + fireEvent.click(mintButton()); + await screen.findByText("one-time-password-123"); + await expectNoA11yViolations(document.body); + }); + + it("surfaces a server-side refusal inline", async () => { + mintNodeScepChallenge.mockRejectedValue(new Error('node has no profile named "bogus"')); + renderDialog(); + fireEvent.click(mintButton()); + await waitFor(() => expect(screen.getByText(/no profile named/i)).toBeInTheDocument()); + }); +}); diff --git a/apps/console/src/components/mint-node-scep-challenge-dialog.tsx b/apps/console/src/components/mint-node-scep-challenge-dialog.tsx new file mode 100644 index 0000000..6d22548 --- /dev/null +++ b/apps/console/src/components/mint-node-scep-challenge-dialog.tsx @@ -0,0 +1,139 @@ +/* +Copyright The CryptOS Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { Button, Dialog, Field, Input, Notice, ShownOnceSecret } from "@cryptos-pki/ui"; +import { useState } from "react"; + +import { mintNodeScepChallenge } from "@/lib/node-scep-challenges"; + +const parseBoundNames = (raw: string): string[] => + raw + .split(",") + .map((n) => n.trim()) + .filter((n) => n !== ""); + +// MintNodeScepChallengeDialog mints a one-time SCEP challenge password on a +// managed node, for example to enroll a network device via its SCEP +// trustpoint. The plaintext lives only in this dialog's state: the page is +// told a challenge was made, never what the password is, and closing the +// dialog discards it. +export const MintNodeScepChallengeDialog = ({ + nodeName, + onClose, + onMinted, +}: { + nodeName: string; + onClose: () => void; + onMinted: () => void; +}) => { + const [profile, setProfile] = useState(""); + const [ttlSeconds, setTtlSeconds] = useState("3600"); + const [boundNames, setBoundNames] = useState(""); + const [pending, setPending] = useState(false); + const [error, setError] = useState(null); + const [challengePassword, setChallengePassword] = useState(""); + + const close = () => { + setChallengePassword(""); + onClose(); + }; + + const mint = () => { + setPending(true); + setError(null); + mintNodeScepChallenge(nodeName, { + boundNames: parseBoundNames(boundNames), + profile: profile.trim(), + ttlSeconds: Number(ttlSeconds) || 0, + }) + .then((result) => { + setChallengePassword(result.challengePassword); + setPending(false); + onMinted(); + }) + .catch((error_: unknown) => { + setError(error_ instanceof Error ? error_.message : "Mint failed"); + setPending(false); + }); + }; + + return ( + + + + + ) + } + onClose={close} + open + title="Mint a SCEP challenge" + > + {challengePassword ? ( + + ) : ( + <> + + setProfile(e.target.value)} + value={profile} + /> + + + setTtlSeconds(e.target.value)} + type="number" + value={ttlSeconds} + /> + + + setBoundNames(e.target.value)} + placeholder="switch-1.example.org, 10.0.0.5" + value={boundNames} + /> + + {error ? ( + + {error} + + ) : null} + + )} + + ); +}; diff --git a/apps/console/src/components/node-scep-challenges.test.tsx b/apps/console/src/components/node-scep-challenges.test.tsx new file mode 100644 index 0000000..634102b --- /dev/null +++ b/apps/console/src/components/node-scep-challenges.test.tsx @@ -0,0 +1,61 @@ +/* +Copyright The CryptOS Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { render, screen } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +import { NodeScepChallenges } from "@/components/node-scep-challenges"; +import { expectNoA11yViolations } from "@/test/axe"; + +let level: "admin" | "operator" | "viewer" = "operator"; +vi.mock("@/context/auth", () => ({ + useOptionalAuth: () => ({ + operator: { commonName: "op@acme.example", level, serial: "AA" }, + status: "authenticated", + }), +})); + +describe("NodeScepChallenges", () => { + beforeEach(() => { + level = "operator"; + }); + + it("has no axe violations", async () => { + const { container } = render(); + await screen.findByText("ch-mock-1"); + await expectNoA11yViolations(container); + }); + + it("lists the node's SCEP challenges", async () => { + render(); + expect(await screen.findByText("ch-mock-1")).toBeInTheDocument(); + }); + + it("shows Mint and Revoke to an operator", async () => { + render(); + await screen.findByText("ch-mock-1"); + expect(screen.getByRole("button", { name: /mint challenge/i })).toBeInTheDocument(); + expect(screen.getByRole("button", { name: /^revoke$/i })).toBeInTheDocument(); + }); + + it("hides Mint and Revoke from a viewer", async () => { + level = "viewer"; + render(); + await screen.findByText("ch-mock-1"); + expect(screen.queryByRole("button", { name: /mint challenge/i })).not.toBeInTheDocument(); + expect(screen.queryByRole("button", { name: /^revoke$/i })).not.toBeInTheDocument(); + }); +}); diff --git a/apps/console/src/components/node-scep-challenges.tsx b/apps/console/src/components/node-scep-challenges.tsx new file mode 100644 index 0000000..1717032 --- /dev/null +++ b/apps/console/src/components/node-scep-challenges.tsx @@ -0,0 +1,145 @@ +/* +Copyright The CryptOS Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { + Button, + DataTable, + type DataTableColumn, + EmptyState, + IconCertificates, +} from "@cryptos-pki/ui"; +import { useEffect, useState } from "react"; + +import { MintNodeScepChallengeDialog } from "@/components/mint-node-scep-challenge-dialog"; +import { RevokeNodeScepChallengeDialog } from "@/components/revoke-node-scep-challenge-dialog"; +import { useOptionalAuth } from "@/context/auth"; +import { fleetErrorMessage } from "@/lib/fleet/error-copy"; +import { listNodeScepChallenges, type NodeScepChallenge } from "@/lib/node-scep-challenges"; + +// NodeScepChallenges lists a managed node's usable SCEP challenges and lets +// an operator mint a new one-time challenge password or revoke an unused +// one. Minting and revoking need operator level or above, the node's own +// write paths; viewers see the list only. +export const NodeScepChallenges = ({ nodeName }: { nodeName: string }) => { + const isOperator = useOptionalAuth()?.operator?.level !== "viewer"; + const [challenges, setChallenges] = useState([]); + const [status, setStatus] = useState<"error" | "loading" | "ready">("loading"); + const [loadError, setLoadError] = useState(""); + const [showMint, setShowMint] = useState(false); + const [revokeTarget, setRevokeTarget] = useState(null); + const [refreshKey, setRefreshKey] = useState(0); + + useEffect(() => { + let cancelled = false; + setStatus("loading"); + listNodeScepChallenges(nodeName) + .then((result) => { + if (cancelled) return; + setChallenges(result); + setStatus("ready"); + }) + .catch((error: unknown) => { + if (cancelled) return; + setLoadError(fleetErrorMessage(error, "Failed to load the node's SCEP challenges")); + setStatus("error"); + }); + return () => { + cancelled = true; + }; + }, [nodeName, refreshKey]); + + const refresh = () => setRefreshKey((k) => k + 1); + + const columns: DataTableColumn[] = [ + { cell: (c) => c.id, header: "ID", id: "id" }, + { cell: (c) => c.profile, header: "Profile", id: "profile" }, + { + cell: (c) => (c.boundNames.length > 0 ? c.boundNames.join(", ") : "—"), + header: "Bound names", + id: "boundNames", + }, + { cell: (c) => c.expiresAt.slice(0, 16).replace("T", " "), header: "Expires", id: "expiresAt" }, + { cell: (c) => c.createdByCn, header: "Minted by", id: "createdByCn" }, + { + cell: (c) => + isOperator ? ( + + ) : null, + header: Actions, + id: "actions", + mobile: "action", + }, + ]; + + return ( +
+ {isOperator ? ( +
+ +
+ ) : null} + + + } + error={ + + } + label="SCEP challenges" + rowKey={(c) => c.id} + rows={challenges} + status={status} + /> + + {showMint ? ( + setShowMint(false)} + onMinted={() => { + refresh(); + }} + /> + ) : null} + {revokeTarget ? ( + setRevokeTarget(null)} + onDone={() => { + setRevokeTarget(null); + refresh(); + }} + profile={revokeTarget.profile} + /> + ) : null} +
+ ); +}; diff --git a/apps/console/src/components/revoke-node-scep-challenge-dialog.test.tsx b/apps/console/src/components/revoke-node-scep-challenge-dialog.test.tsx new file mode 100644 index 0000000..7a962a1 --- /dev/null +++ b/apps/console/src/components/revoke-node-scep-challenge-dialog.test.tsx @@ -0,0 +1,77 @@ +/* +Copyright The CryptOS Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +import { RevokeNodeScepChallengeDialog } from "@/components/revoke-node-scep-challenge-dialog"; +import { expectNoA11yViolations } from "@/test/axe"; + +const revokeNodeScepChallenge = vi.fn(); +vi.mock("@/lib/node-scep-challenges", () => ({ + revokeNodeScepChallenge: (...a: unknown[]) => revokeNodeScepChallenge(...a), +})); + +const revokeButton = () => screen.getByRole("button", { name: /^revoke$/i }); + +const renderDialog = () => + render( + , + ); + +describe("RevokeNodeScepChallengeDialog", () => { + beforeEach(() => { + revokeNodeScepChallenge.mockReset(); + revokeNodeScepChallenge.mockImplementation(() => Promise.resolve()); + }); + + it("has no axe violations", async () => { + renderDialog(); + await expectNoA11yViolations(document.body); + }); + + it("confirms the revoke with the challenge id and calls onDone", async () => { + const onDone = vi.fn(); + render( + , + ); + fireEvent.click(revokeButton()); + + await waitFor(() => + expect(revokeNodeScepChallenge).toHaveBeenCalledWith("acme-edge-07", "ch-1"), + ); + await waitFor(() => expect(onDone).toHaveBeenCalled()); + }); + + it("surfaces a server-side refusal inline", async () => { + revokeNodeScepChallenge.mockRejectedValue(new Error("no challenge with that id")); + renderDialog(); + fireEvent.click(revokeButton()); + await waitFor(() => expect(screen.getByText(/no challenge with that id/i)).toBeInTheDocument()); + }); +}); diff --git a/apps/console/src/components/revoke-node-scep-challenge-dialog.tsx b/apps/console/src/components/revoke-node-scep-challenge-dialog.tsx new file mode 100644 index 0000000..5aebf68 --- /dev/null +++ b/apps/console/src/components/revoke-node-scep-challenge-dialog.tsx @@ -0,0 +1,82 @@ +/* +Copyright The CryptOS Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { Button, Dialog, Notice } from "@cryptos-pki/ui"; +import { useState } from "react"; + +import { revokeNodeScepChallenge } from "@/lib/node-scep-challenges"; + +// RevokeNodeScepChallengeDialog withdraws a managed node's SCEP challenge +// before it is used or expires. A device that already has the challenge +// password cannot enroll with it once revoked. +export const RevokeNodeScepChallengeDialog = ({ + challengeId, + nodeName, + onClose, + onDone, + profile, +}: { + challengeId: string; + nodeName: string; + onClose: () => void; + onDone: () => void; + profile: string; +}) => { + const [pending, setPending] = useState(false); + const [error, setError] = useState(null); + + const confirm = () => { + setPending(true); + setError(null); + revokeNodeScepChallenge(nodeName, challengeId) + .then(() => { + onDone(); + }) + .catch((error_: unknown) => { + setError(error_ instanceof Error ? error_.message : "Revoke failed"); + setPending(false); + }); + }; + + return ( + + + + + } + onClose={onClose} + open + title="Revoke SCEP challenge" + variant="destructive" + > + +

A device that already has this challenge password can no longer enroll with it.

+
+ {error ? ( + + {error} + + ) : null} +
+ ); +}; diff --git a/apps/console/src/lib/node-scep-challenges.live.test.ts b/apps/console/src/lib/node-scep-challenges.live.test.ts new file mode 100644 index 0000000..bf75849 --- /dev/null +++ b/apps/console/src/lib/node-scep-challenges.live.test.ts @@ -0,0 +1,108 @@ +/* +Copyright The CryptOS Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +const listNodeScepChallenges = vi.fn(() => + Promise.resolve({ + challenges: [ + { + boundNames: ["switch-1.example.org"], + createdAt: "2026-01-01T00:00:00Z", + createdByCn: "admin@acme.example", + expiresAt: "2026-01-02T00:00:00Z", + id: "ch-live-1", + profile: "network-device", + }, + ], + }), +); +const mintNodeScepChallenge = vi.fn(() => + Promise.resolve({ + challenge: { + boundNames: [], + createdAt: "2026-01-01T00:00:00Z", + createdByCn: "admin@acme.example", + expiresAt: "2026-01-02T00:00:00Z", + id: "ch-live-new", + profile: "network-device", + }, + challengePassword: "live-one-time-password", + }), +); +const revokeNodeScepChallenge = vi.fn(() => Promise.resolve({ challenge: { id: "ch-live-1" } })); +vi.mock("@/lib/fleet/client", () => ({ + fleetClient: () => ({ listNodeScepChallenges, mintNodeScepChallenge, revokeNodeScepChallenge }), +})); + +import { + listNodeScepChallenges as listNodeScepChallengesLib, + mintNodeScepChallenge as mintNodeScepChallengeLib, + revokeNodeScepChallenge as revokeNodeScepChallengeLib, +} from "@/lib/node-scep-challenges"; + +describe("node-scep-challenges live path", () => { + beforeEach(() => { + listNodeScepChallenges.mockClear(); + mintNodeScepChallenge.mockClear(); + revokeNodeScepChallenge.mockClear(); + vi.stubEnv("VITE_FLEET_MODE", "live"); + }); + + afterEach(() => { + vi.unstubAllEnvs(); + }); + + it("listNodeScepChallenges forwards the node name and flattens the response", async () => { + const challenges = await listNodeScepChallengesLib("acme-issuing-01"); + expect(listNodeScepChallenges).toHaveBeenCalledWith( + expect.objectContaining({ nodeName: "acme-issuing-01" }), + ); + expect(challenges).toEqual([ + { + boundNames: ["switch-1.example.org"], + createdAt: "2026-01-01T00:00:00Z", + createdByCn: "admin@acme.example", + expiresAt: "2026-01-02T00:00:00Z", + id: "ch-live-1", + profile: "network-device", + }, + ]); + }); + + it("mintNodeScepChallenge forwards profile, ttl_seconds and bound_names", async () => { + const result = await mintNodeScepChallengeLib("acme-issuing-01", { + boundNames: ["switch-1.example.org"], + profile: "network-device", + ttlSeconds: 3600, + }); + expect(mintNodeScepChallenge).toHaveBeenCalledWith({ + boundNames: ["switch-1.example.org"], + nodeName: "acme-issuing-01", + profile: "network-device", + ttlSeconds: 3600, + }); + expect(result.challengePassword).toBe("live-one-time-password"); + }); + + it("revokeNodeScepChallenge forwards the id", async () => { + await revokeNodeScepChallengeLib("acme-issuing-01", "ch-live-1"); + expect(revokeNodeScepChallenge).toHaveBeenCalledWith({ + id: "ch-live-1", + nodeName: "acme-issuing-01", + }); + }); +}); diff --git a/apps/console/src/lib/node-scep-challenges.test.ts b/apps/console/src/lib/node-scep-challenges.test.ts new file mode 100644 index 0000000..add5060 --- /dev/null +++ b/apps/console/src/lib/node-scep-challenges.test.ts @@ -0,0 +1,49 @@ +/* +Copyright The CryptOS Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { describe, expect, it } from "vitest"; + +import { + listNodeScepChallenges, + mintNodeScepChallenge, + revokeNodeScepChallenge, +} from "@/lib/node-scep-challenges"; + +describe("listNodeScepChallenges (mock mode)", () => { + it("returns a deterministic demo challenge", async () => { + const challenges = await listNodeScepChallenges("acme-issuing-01"); + expect(challenges.length).toBeGreaterThan(0); + }); +}); + +describe("mintNodeScepChallenge (mock mode)", () => { + it("returns a non-empty one-time password and a matching challenge", async () => { + const result = await mintNodeScepChallenge("acme-issuing-01", { + boundNames: ["switch-1.example.org"], + profile: "network-device", + ttlSeconds: 3600, + }); + expect(result.challengePassword.length).toBeGreaterThan(0); + expect(result.challenge.profile).toBe("network-device"); + expect(result.challenge.boundNames).toEqual(["switch-1.example.org"]); + }); +}); + +describe("revokeNodeScepChallenge", () => { + it("is a no-op that resolves in mock mode", async () => { + await expect(revokeNodeScepChallenge("acme-issuing-01", "ch-mock-1")).resolves.toBeUndefined(); + }); +}); diff --git a/apps/console/src/lib/node-scep-challenges.ts b/apps/console/src/lib/node-scep-challenges.ts new file mode 100644 index 0000000..65ff3b4 --- /dev/null +++ b/apps/console/src/lib/node-scep-challenges.ts @@ -0,0 +1,122 @@ +/* +Copyright The CryptOS Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { fleetClient } from "@/lib/fleet/client"; +import { fleetMode } from "@/lib/fleet/mode"; + +// NodeScepChallenge is a one-time SCEP challenge on a managed node, without +// the challenge itself, which only mintNodeScepChallenge's result carries. +export interface NodeScepChallenge { + boundNames: string[]; + createdAt: string; + createdByCn: string; + expiresAt: string; + id: string; + profile: string; +} + +const mockChallenges = (): NodeScepChallenge[] => [ + { + boundNames: [], + createdAt: "2026-10-14T00:00:00Z", + createdByCn: "admin@acme.example", + expiresAt: "2026-10-15T00:00:00Z", + id: "ch-mock-1", + profile: "network-device", + }, +]; + +// listNodeScepChallenges lists a managed node's usable SCEP challenges, +// soonest to expire first. Operator level or above; mock mode returns a +// small canned set. +export const listNodeScepChallenges = async (nodeName: string): Promise => { + if (fleetMode() === "mock") { + return mockChallenges(); + } + + const response = await fleetClient().listNodeScepChallenges({ nodeName }); + return response.challenges.map((c) => ({ + boundNames: c.boundNames, + createdAt: c.createdAt, + createdByCn: c.createdByCn, + expiresAt: c.expiresAt, + id: c.id, + profile: c.profile, + })); +}; + +export interface MintNodeScepChallengeInput { + boundNames: string[]; + profile: string; + ttlSeconds: number; +} + +export interface MintNodeScepChallengeResult { + challenge: NodeScepChallenge; + challengePassword: string; +} + +// mintNodeScepChallenge mints a one-time SCEP challenge password on a +// managed node, for example to enroll a network device via its SCEP +// trustpoint. The password is returned once; the caller must not persist it +// anywhere but the operator's own clipboard. +export const mintNodeScepChallenge = async ( + nodeName: string, + { boundNames, profile, ttlSeconds }: MintNodeScepChallengeInput, +): Promise => { + if (fleetMode() === "mock") { + return { + challenge: { + boundNames, + createdAt: new Date().toISOString(), + createdByCn: "you@acme.example", + expiresAt: new Date(Date.now() + ttlSeconds * 1000).toISOString(), + id: "ch-mock-new", + profile, + }, + challengePassword: "mock-challenge-password-00000000", + }; + } + + const response = await fleetClient().mintNodeScepChallenge({ + boundNames, + nodeName, + profile, + ttlSeconds, + }); + const challenge = response.challenge; + return { + challenge: { + boundNames: challenge?.boundNames ?? [], + createdAt: challenge?.createdAt ?? "", + createdByCn: challenge?.createdByCn ?? "", + expiresAt: challenge?.expiresAt ?? "", + id: challenge?.id ?? "", + profile: challenge?.profile ?? "", + }, + challengePassword: response.challengePassword, + }; +}; + +// revokeNodeScepChallenge withdraws a managed node's SCEP challenge before it +// is used or expires. +export const revokeNodeScepChallenge = async (nodeName: string, id: string): Promise => { + if (fleetMode() === "mock") { + return; + } + + await fleetClient().revokeNodeScepChallenge({ id, nodeName }); +}; diff --git a/apps/console/src/pages/node-detail.live.test.tsx b/apps/console/src/pages/node-detail.live.test.tsx index 9b077e6..9bd08f7 100644 --- a/apps/console/src/pages/node-detail.live.test.tsx +++ b/apps/console/src/pages/node-detail.live.test.tsx @@ -92,6 +92,7 @@ vi.mock("@/lib/fleet/client", () => ({ listCertificates: () => Promise.resolve(listCertificatesResult), listNodeAuditEvents: () => Promise.resolve({ entries: [], nextPageToken: "" }), listNodes: () => Promise.resolve(listNodesResult), + listNodeScepChallenges: () => Promise.resolve({ challenges: [] }), listNodeTsaCertificates: () => Promise.resolve({ certificates: [] }), verifyNodeAuditChain: () => Promise.resolve({ entryCount: 0n, firstBrokenSequence: 0n, intact: true, reason: "" }), @@ -123,6 +124,7 @@ describe("NodeDetailPage live", () => { expect(screen.getByText("Certificates")).toBeInTheDocument(); await screen.findByRole("button", { name: "Verify chain" }); await screen.findByText(/not running/i); + await screen.findByText(/no usable scep challenges/i); await screen.findByText(/0\.1\.0/); }); @@ -132,6 +134,7 @@ describe("NodeDetailPage live", () => { expect(await screen.findByRole("link", { name: "AA11" })).toBeInTheDocument(); await screen.findByRole("button", { name: "Verify chain" }); await screen.findByText(/not running/i); + await screen.findByText(/no usable scep challenges/i); await screen.findByText(/0\.1\.0/); }); }); diff --git a/apps/console/src/pages/node-detail.test.tsx b/apps/console/src/pages/node-detail.test.tsx index 976d17c..cf4fd58 100644 --- a/apps/console/src/pages/node-detail.test.tsx +++ b/apps/console/src/pages/node-detail.test.tsx @@ -40,10 +40,11 @@ describe("NodeDetailPage trust chain", () => { it("has no axe violations", async () => { const { container } = renderAt("/nodes/acme-issuing-01"); - // Lets the TSA certificates and image lifecycle panels' async fetches + // Lets the node detail panels' async fetches // settle under act() instead of resolving after the test returns. await screen.findByText("0a1b2c3d"); await screen.findByText(/7c3a9e2f1b6d \u00B7 0\.1\.0/); + await screen.findByText("ch-mock-1"); await expectNoA11yViolations(container); }); @@ -54,6 +55,7 @@ describe("NodeDetailPage trust chain", () => { await screen.findByRole("button", { name: "Verify chain" }); await screen.findByText("0a1b2c3d"); await screen.findByText(/7c3a9e2f1b6d \u00B7 0\.1\.0/); + await screen.findByText("ch-mock-1"); const chain = screen.getByText(/trust chain/i).closest("div")?.parentElement as HTMLElement; expect(within(chain).getByRole("link", { name: "acme-root-01" })).toHaveAttribute( "href", diff --git a/apps/console/src/pages/node-detail.tsx b/apps/console/src/pages/node-detail.tsx index f5271bd..90d51dc 100644 --- a/apps/console/src/pages/node-detail.tsx +++ b/apps/console/src/pages/node-detail.tsx @@ -31,6 +31,7 @@ import { NodeAuditLog } from "@/components/node-audit-log"; import { NodeChainValidate } from "@/components/node-chain-validate"; import { NodeDetailPanel } from "@/components/node-detail-panel"; import { NodeImageLifecycle } from "@/components/node-image-lifecycle"; +import { NodeScepChallenges } from "@/components/node-scep-challenges"; import { NodeTsaCertificates } from "@/components/node-tsa-certificates"; import { roleLabels } from "@/lib/fleet/labels"; import { chainToRoot, useNode } from "@/lib/nodes"; @@ -170,6 +171,14 @@ export const NodeDetailPage = () => { + +
+ SCEP challenges +
+
+ +
+
diff --git a/packages/api-client/proto-refs.env b/packages/api-client/proto-refs.env index d40c912..f294798 100644 --- a/packages/api-client/proto-refs.env +++ b/packages/api-client/proto-refs.env @@ -2,4 +2,4 @@ # `npm run generate -w @cryptos-pki/api-client`, and commit src/gen in the # same change. CRYPTOS_NODE_REF=8d8b52d5bafd4247db69c003a588ccf394d03f79 -CRYPTOS_MANAGER_REF=1b0e4f72c5d3d6b2c87b87a4c2daa891c5e04151 +CRYPTOS_MANAGER_REF=9a707eed187fc0335b09ad8f1b49465bb9290ac1 diff --git a/packages/api-client/src/gen/cryptos/fleet/v1/fleet_pb.ts b/packages/api-client/src/gen/cryptos/fleet/v1/fleet_pb.ts index 2cadc7d..967784c 100644 --- a/packages/api-client/src/gen/cryptos/fleet/v1/fleet_pb.ts +++ b/packages/api-client/src/gen/cryptos/fleet/v1/fleet_pb.ts @@ -18,7 +18,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file cryptos/fleet/v1/fleet.proto. */ export const file_cryptos_fleet_v1_fleet: GenFile = /*@__PURE__*/ - fileDesc("ChxjcnlwdG9zL2ZsZWV0L3YxL2ZsZWV0LnByb3RvEhBjcnlwdG9zLmZsZWV0LnYxIhIKEExpc3ROb2Rlc1JlcXVlc3QiQQoRTGlzdE5vZGVzUmVzcG9uc2USLAoFbm9kZXMYASADKAsyHS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVTdW1tYXJ5Ii8KDkdldE5vZGVSZXF1ZXN0EgwKBG5hbWUYASABKAkSDwoHbm9kZV9pZBgCIAEoCSI9Cg9HZXROb2RlUmVzcG9uc2USKgoEbm9kZRgBIAEoCzIcLmNyeXB0b3MuZmxlZXQudjEuTm9kZURldGFpbCI4ChdMaXN0Q2VydGlmaWNhdGVzUmVxdWVzdBIMCgRub2RlGAEgASgJEg8KB25vZGVfaWQYAiABKAkiTwoYTGlzdENlcnRpZmljYXRlc1Jlc3BvbnNlEjMKDGNlcnRpZmljYXRlcxgBIAMoCzIdLmNyeXB0b3MuZmxlZXQudjEuQ2VydGlmaWNhdGUiFQoTTGlzdFByb2ZpbGVzUmVxdWVzdCJKChRMaXN0UHJvZmlsZXNSZXNwb25zZRIyCgVpdGVtcxgBIAMoCzIjLmNyeXB0b3Mubm9kZS52MS5DZXJ0aWZpY2F0ZVByb2ZpbGUiTAoUQ3JlYXRlUHJvZmlsZVJlcXVlc3QSNAoHcHJvZmlsZRgBIAEoCzIjLmNyeXB0b3Mubm9kZS52MS5DZXJ0aWZpY2F0ZVByb2ZpbGUiFwoVQ3JlYXRlUHJvZmlsZVJlc3BvbnNlIkwKFFVwZGF0ZVByb2ZpbGVSZXF1ZXN0EjQKB3Byb2ZpbGUYASABKAsyIy5jcnlwdG9zLm5vZGUudjEuQ2VydGlmaWNhdGVQcm9maWxlIhcKFVVwZGF0ZVByb2ZpbGVSZXNwb25zZSIkChREZWxldGVQcm9maWxlUmVxdWVzdBIMCgRuYW1lGAEgASgJIhcKFURlbGV0ZVByb2ZpbGVSZXNwb25zZSJVChlBcHBseVByb2ZpbGVUb05vZGVSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIUCgxwcm9maWxlX25hbWUYAiABKAkSDwoHbm9kZV9pZBgDIAEoCSJJChpBcHBseVByb2ZpbGVUb05vZGVSZXNwb25zZRISCgpnZW5lcmF0aW9uGAEgASgEEhcKD3JlcXVpcmVzX3JlYm9vdBgCIAEoCCJBChxTZXRQcm9maWxlUmVxdWVzdGFibGVSZXF1ZXN0EgwKBG5hbWUYASABKAkSEwoLcmVxdWVzdGFibGUYAiABKAgiHwodU2V0UHJvZmlsZVJlcXVlc3RhYmxlUmVzcG9uc2UiIAoeTGlzdFJlcXVlc3RhYmxlUHJvZmlsZXNSZXF1ZXN0IlUKH0xpc3RSZXF1ZXN0YWJsZVByb2ZpbGVzUmVzcG9uc2USMgoFaXRlbXMYASADKAsyIy5jcnlwdG9zLm5vZGUudjEuQ2VydGlmaWNhdGVQcm9maWxlIhUKE0xpc3RBZGFwdGVyc1JlcXVlc3QiSgoUTGlzdEFkYXB0ZXJzUmVzcG9uc2USMgoFaXRlbXMYASADKAsyIy5jcnlwdG9zLmZsZWV0LnYxLkVucm9sbG1lbnRBZGFwdGVyIjkKGFNldEFkYXB0ZXJFbmFibGVkUmVxdWVzdBIMCgRuYW1lGAEgASgJEg8KB2VuYWJsZWQYAiABKAgiUQoZU2V0QWRhcHRlckVuYWJsZWRSZXNwb25zZRI0CgdhZGFwdGVyGAEgASgLMiMuY3J5cHRvcy5mbGVldC52MS5FbnJvbGxtZW50QWRhcHRlciISChBMaXN0QXVkaXRSZXF1ZXN0IkAKEUxpc3RBdWRpdFJlc3BvbnNlEisKBWl0ZW1zGAEgAygLMhwuY3J5cHRvcy5mbGVldC52MS5BdWRpdEV2ZW50IhgKFkxpc3RFbnJvbGxtZW50c1JlcXVlc3QiTQoXTGlzdEVucm9sbG1lbnRzUmVzcG9uc2USMgoFaXRlbXMYASADKAsyIy5jcnlwdG9zLmZsZWV0LnYxLkVucm9sbG1lbnRSZXF1ZXN0IogCCgtOb2RlU3VtbWFyeRIMCgRuYW1lGAEgASgJEg8KB2FkZHJlc3MYAiABKAkSDAoEcm9sZRgDIAEoCRIWCg5pZGVudGl0eV9zdGF0ZRgEIAEoCRIKCgJjbhgFIAEoCRIOCgZpc3N1ZXIYBiABKAkSKAoGaGVhbHRoGAcgASgOMhguY3J5cHRvcy5mbGVldC52MS5IZWFsdGgSFQoNaGVhbHRoX2RldGFpbBgIIAEoCRIKCgJpZBgJIAEoCRIyCglwcm90b2NvbHMYCiADKAsyHy5jcnlwdG9zLm5vZGUudjEuUHJvdG9jb2xTdGF0dXMSFwoPcmVib290X3JlcXVpcmVkGAsgASgIIkkKDE5vZGVJZGVudGl0eRIRCgljaGFpbl9wZW0YASABKAkSEQoJY2hhaW5fZGVyGAIgAygMEhMKC2xlYWZfc2hhMjU2GAMgASgJIqkBCgpOb2RlRGV0YWlsEi4KB3N1bW1hcnkYASABKAsyHS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVTdW1tYXJ5EjAKCGlkZW50aXR5GAIgASgLMh4uY3J5cHRvcy5mbGVldC52MS5Ob2RlSWRlbnRpdHkSFQoNdHBtX2F2YWlsYWJsZRgDIAEoCBISCgpib290X2NvdW50GAQgASgEEg4KBnVwdGltZRgFIAEoCSLYAQoLQ2VydGlmaWNhdGUSDgoGc2VyaWFsGAEgASgJEhIKCnN1YmplY3RfY24YAiABKAkSEwoLaXNzdWVyX25vZGUYAyABKAkSDAoEa2luZBgEIAEoCRIOCgZzdGF0dXMYBSABKAkSEgoKbm90X2JlZm9yZRgGIAEoCRIRCglub3RfYWZ0ZXIYByABKAkSDwoHcHJvZmlsZRgIIAEoCRISCgpyZXZva2VkX2F0GAkgASgJEg4KBnJlYXNvbhgKIAEoCRIWCg5pc3N1ZXJfbm9kZV9pZBgLIAEoCSKNAQoRRW5yb2xsbWVudEFkYXB0ZXISDAoEa2luZBgBIAEoCRIMCgRuYW1lGAIgASgJEhAKCGVuZHBvaW50GAMgASgJEg8KB3Byb2ZpbGUYBCABKAkSDwoHZW5hYmxlZBgFIAEoCBISCgpjaGFsbGVuZ2VzGAYgAygJEhQKDGdwb190ZW1wbGF0ZRgHIAEoCSK8AgoKQXVkaXRFdmVudBIKCgJpZBgBIAEoCRIKCgJhdBgCIAEoCRIMCgRraW5kGAMgASgJEg8KB3N1bW1hcnkYBCABKAkSEwoLdGFyZ2V0X2tpbmQYBSABKAkSEwoLdGFyZ2V0X3BhdGgYBiABKAkSEgoKYWN0b3Jfa2luZBgHIAEoCRIQCghhY3Rvcl9jbhgIIAEoCRIUCgxhY3Rvcl9zZXJpYWwYCSABKAkSDgoGa2V5X2lkGAogASgJEgsKA3ZpYRgLIAEoCRIMCgR0b29sGAwgASgJEhYKDnJlcXVlc3RfZGlnZXN0GA0gASgJEg8KB291dGNvbWUYDiABKAkSEwoLYXBwcm92YWxfaWQYDyABKAkSFwoPYXBwcm92ZXJfc2VyaWFsGBAgASgJEg8KB25vZGVfaWQYESABKAki7wIKEUVucm9sbG1lbnRSZXF1ZXN0EgoKAmlkGAEgASgJEhUKDXByb3Bvc2VkX25hbWUYAiABKAkSDAoEcm9sZRgDIAEoCRIRCglwYXJlbnRfY24YBCABKAkSDwoHYWRkcmVzcxgFIAEoCRIOCgZzdGF0dXMYBiABKAkSGwoTYXR0ZXN0YXRpb25fc3VtbWFyeRgHIAEoCRIbChNhdHRlc3RhdGlvbl9ub2RlX2lkGAggASgJEhQKDGNzcl9rZXlfdHlwZRgJIAEoCRIWCg5jc3Jfc3ViamVjdF9jbhgKIAEoCRIUCgxyZXF1ZXN0ZWRfYXQYCyABKAkSGAoQcmVqZWN0aW9uX3JlYXNvbhgMIAEoCRIaChJhZG1pdHRlZF9ub2RlX25hbWUYDSABKAkSDAoEa2luZBgOIAEoCRIZChFwaW5uZWRfa2V5X3NoYTI1NhgPIAEoCRIYChBhZG1pdHRlZF9ub2RlX2lkGBAgASgJIswBChdDcmVhdGVFbnJvbGxtZW50UmVxdWVzdBIMCgRraW5kGAEgASgJEhUKDW5vZGVfZW5kcG9pbnQYAiABKAkSFgoOYWRtaW5fY2VydF9wZW0YAyABKAkSFQoNYWRtaW5fa2V5X3BlbRgEIAEoCRIOCgZjYV9wZW0YBSABKAkSEgoKY2hpbGRfbm9kZRgGIAEoCRIRCglwYXJlbnRfY24YByABKAkSDwoHcHJvZmlsZRgIIAEoCRIVCg1jaGlsZF9ub2RlX2lkGAkgASgJIlMKGENyZWF0ZUVucm9sbG1lbnRSZXNwb25zZRI3CgplbnJvbGxtZW50GAEgASgLMiMuY3J5cHRvcy5mbGVldC52MS5FbnJvbGxtZW50UmVxdWVzdCJ8ChhBcHByb3ZlRW5yb2xsbWVudFJlcXVlc3QSCgoCaWQYASABKAkSFQoNbm9kZV9lbmRwb2ludBgCIAEoCRIWCg5hZG1pbl9jZXJ0X3BlbRgDIAEoCRIVCg1hZG1pbl9rZXlfcGVtGAQgASgJEg4KBmNhX3BlbRgFIAEoCSJUChlBcHByb3ZlRW5yb2xsbWVudFJlc3BvbnNlEjcKCmVucm9sbG1lbnQYASABKAsyIy5jcnlwdG9zLmZsZWV0LnYxLkVucm9sbG1lbnRSZXF1ZXN0IjUKF1JlamVjdEVucm9sbG1lbnRSZXF1ZXN0EgoKAmlkGAEgASgJEg4KBnJlYXNvbhgCIAEoCSJTChhSZWplY3RFbnJvbGxtZW50UmVzcG9uc2USNwoKZW5yb2xsbWVudBgBIAEoCzIjLmNyeXB0b3MuZmxlZXQudjEuRW5yb2xsbWVudFJlcXVlc3QiDwoNV2hvQW1JUmVxdWVzdCI9ChBPcGVyYXRvcklkZW50aXR5EgoKAmNuGAEgASgJEg4KBnNlcmlhbBgCIAEoCRINCgVsZXZlbBgDIAEoCSJGCg5XaG9BbUlSZXNwb25zZRI0CghvcGVyYXRvchgBIAEoCzIiLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JJZGVudGl0eSJnChhSZXZva2VDZXJ0aWZpY2F0ZVJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEhIKCnNlcmlhbF9oZXgYAiABKAkSEwoLcmVhc29uX2NvZGUYAyABKAUSDwoHbm9kZV9pZBgEIAEoCSJYChlSZXZva2VDZXJ0aWZpY2F0ZVJlc3BvbnNlEhIKCnNlcmlhbF9oZXgYASABKAkSEgoKcmV2b2tlZF9hdBgCIAEoCRITCgtyZWFzb25fY29kZRgDIAEoBSI+ChVHZXRDZXJ0aWZpY2F0ZVJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEhIKCnNlcmlhbF9oZXgYAiABKAkiaAoWR2V0Q2VydGlmaWNhdGVSZXNwb25zZRIXCg9jZXJ0aWZpY2F0ZV9wZW0YASABKAkSEQoJY2hhaW5fcGVtGAIgASgJEg4KBnN0YXR1cxgDIAEoCRISCgpyZXZva2VkX2F0GAQgASgJIl0KEElzc3VlTGVhZlJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEg8KB2Nzcl9kZXIYAiABKAwSFAoMcHJvZmlsZV9uYW1lGAMgASgJEg8KB25vZGVfaWQYBCABKAkiJQoRSXNzdWVMZWFmUmVzcG9uc2USEAoIY2VydF9kZXIYASABKAwiTAoQUmVrZXlOb2RlUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSFAoMcHJvZmlsZV9uYW1lGAIgASgJEg8KB25vZGVfaWQYAyABKAkiTQoRUmVrZXlOb2RlUmVzcG9uc2USEgoKc3ViamVjdF9jbhgBIAEoCRIRCglpc3N1ZXJfY24YAiABKAkSEQoJY2hhaW5fbGVuGAMgASgFIjoKFEdldE5vZGVDb25maWdSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJIkcKFUdldE5vZGVDb25maWdSZXNwb25zZRIuCgZjb25maWcYASABKAsyHi5jcnlwdG9zLm5vZGUudjEuTWFjaGluZUNvbmZpZyJsChZBcHBseU5vZGVDb25maWdSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIuCgZjb25maWcYAiABKAsyHi5jcnlwdG9zLm5vZGUudjEuTWFjaGluZUNvbmZpZxIPCgdub2RlX2lkGAMgASgJIkYKF0FwcGx5Tm9kZUNvbmZpZ1Jlc3BvbnNlEhIKCmdlbmVyYXRpb24YASABKAQSFwoPcmVxdWlyZXNfcmVib290GAIgASgIInAKFlNldE5vZGVQcm90b2NvbFJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEjIKCHByb3RvY29sGAIgASgOMiAuY3J5cHRvcy5ub2RlLnYxLlNlcnZpY2VQcm90b2NvbBIPCgdlbmFibGVkGAMgASgIIkYKF1NldE5vZGVQcm90b2NvbFJlc3BvbnNlEhIKCmdlbmVyYXRpb24YASABKAQSFwoPcmVxdWlyZXNfcmVib290GAIgASgIIkwKEkV4cG9ydENBS2V5UmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSEgoKcGFzc3BocmFzZRgCIAEoDBIPCgdub2RlX2lkGAMgASgJIicKE0V4cG9ydENBS2V5UmVzcG9uc2USEAoIZW52ZWxvcGUYASABKAwiXgoSSW1wb3J0Q0FLZXlSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIQCghlbnZlbG9wZRgCIAEoDBISCgpwYXNzcGhyYXNlGAMgASgMEg8KB25vZGVfaWQYBCABKAkiPAoTSW1wb3J0Q0FLZXlSZXNwb25zZRISCgpzdWJqZWN0X2NuGAEgASgJEhEKCWlzc3Vlcl9jbhgCIAEoCSJvCh9SZXZva2VPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0EhIKCnNlcmlhbF9oZXgYASABKAkSEwoLcmVhc29uX2NvZGUYAiABKAUSFQoNaXNzdWVyX3NoYTI1NhgDIAEoCRIMCgRub3RlGAQgASgJInMKIFJldm9rZU9wZXJhdG9yQ3JlZGVudGlhbFJlc3BvbnNlEhIKCnNlcmlhbF9oZXgYASABKAkSEgoKcmV2b2tlZF9hdBgCIAEoCRIVCg1pc3N1ZXJfc2hhMjU2GAMgASgJEhAKCHdhcm5pbmdzGAQgAygJIiAKHkxpc3RPcGVyYXRvckNyZWRlbnRpYWxzUmVxdWVzdCKNAgoST3BlcmF0b3JDcmVkZW50aWFsEhMKC2NvbW1vbl9uYW1lGAEgASgJEhIKCnNlcmlhbF9oZXgYAiABKAkSDQoFbGV2ZWwYAyABKAkSEQoJbm90X2FmdGVyGAQgASgJEg8KB3Jldm9rZWQYBSABKAgSDAoEa2luZBgGIAEoCRIVCg1pc3N1ZXJfc2hhMjU2GAcgASgJEg0KBWVtYWlsGAggASgJEhEKCWZ1bGxfbmFtZRgJIAEoCRISCgpkZW55bGlzdGVkGAogASgIEhMKC2NybF9yZXZva2VkGAsgASgIEhUKDWZpcnN0X3NlZW5fYXQYDCABKAkSFAoMbGFzdF9zZWVuX2F0GA0gASgJIlYKH0xpc3RPcGVyYXRvckNyZWRlbnRpYWxzUmVzcG9uc2USMwoFaXRlbXMYASADKAsyJC5jcnlwdG9zLmZsZWV0LnYxLk9wZXJhdG9yQ3JlZGVudGlhbCJqCiZDcmVhdGVPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0UmVxdWVzdBINCgVsZXZlbBgBIAEoCRINCgVlbWFpbBgCIAEoCRIRCglmdWxsX25hbWUYAyABKAkSDwoHY3NyX2RlchgEIAEoDCKUAQonQ3JlYXRlT3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdFJlc3BvbnNlEhIKCnJlcXVlc3RfaWQYASABKAkSDwoHY3NyX3BlbRgCIAEoCRIXCg9leHRmaWxlX3NlY3Rpb24YAyABKAkSFwoPb3BlbnNzbF9jb21tYW5kGAQgASgJEhIKCmV4cGlyZXNfYXQYBSABKAkiNgolTGlzdE9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3RzUmVxdWVzdBINCgVzdGF0ZRgBIAEoCSJkCiZMaXN0T3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdHNSZXNwb25zZRI6CgVpdGVtcxgBIAMoCzIrLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdCI8CiZDYW5jZWxPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0UmVxdWVzdBISCgpyZXF1ZXN0X2lkGAEgASgJImcKJ0NhbmNlbE9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3RSZXNwb25zZRI8CgdyZXF1ZXN0GAEgASgLMisuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0ItEBChlPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0EgoKAmlkGAEgASgJEg0KBWxldmVsGAIgASgJEg0KBWVtYWlsGAMgASgJEhEKCWZ1bGxfbmFtZRgEIAEoCRIPCgdjc3JfcGVtGAUgASgJEg0KBXN0YXRlGAYgASgJEhUKDWNyZWF0ZWRfYnlfY24YByABKAkSEgoKY3JlYXRlZF9hdBgIIAEoCRISCgpleHBpcmVzX2F0GAkgASgJEhgKEGNvbXBsZXRlZF9zZXJpYWwYCiABKAkiWgofUmVjb3JkT3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdBIQCghjZXJ0X2RlchgBIAEoDBISCgpyZXF1ZXN0X2lkGAIgASgJEhEKCWZ1bGxfbmFtZRgDIAEoCSJuCiBSZWNvcmRPcGVyYXRvckNyZWRlbnRpYWxSZXNwb25zZRI4CgpjcmVkZW50aWFsGAEgASgLMiQuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNyZWRlbnRpYWwSEAoId2FybmluZ3MYAiADKAkiGAoWTGlzdE9wZXJhdG9yQ0FzUmVxdWVzdCJGChdMaXN0T3BlcmF0b3JDQXNSZXNwb25zZRIrCgVpdGVtcxgBIAMoCzIcLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JDQSKQAgoZUmVnaXN0ZXJPcGVyYXRvckNBUmVxdWVzdBITCgtjYV9jZXJ0X2RlchgBIAEoDBINCgN1cmwYAiABKAlIABIRCgdjcmxfZGVyGAMgASgMSAASDgoEbm9uZRgEIAEoCEgAEi0KCW9jc3BfbW9kZRgFIAEoDjIaLmNyeXB0b3MuZmxlZXQudjEuT2NzcE1vZGUSEAoIb2NzcF91cmwYBiABKAkSRQoQYWNrbm93bGVkZ2VtZW50cxgHIAMoDjIrLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JDQUFja25vd2xlZGdlbWVudBIWCg5jb25maXJtX3NoYTI1NhgIIAEoCUIMCgpjcmxfc291cmNlIrABChpSZWdpc3Rlck9wZXJhdG9yQ0FSZXNwb25zZRIxCgtvcGVyYXRvcl9jYRgBIAEoCzIcLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JDQRIRCgljb25maXJtZWQYAiABKAgSFQoNYWRtaW5fZXh0ZmlsZRgDIAEoCRI1CgpvY3NwX3Byb2JlGAQgASgLMiEuY3J5cHRvcy5mbGVldC52MS5PY3NwUHJvYmVSZXN1bHQiTAoXUmV0aXJlT3BlcmF0b3JDQVJlcXVlc3QSDgoGc2hhMjU2GAEgASgJEiEKGWlfdW5kZXJzdGFuZF9zZWxmX2xvY2tvdXQYAiABKAgiTQoYUmV0aXJlT3BlcmF0b3JDQVJlc3BvbnNlEjEKC29wZXJhdG9yX2NhGAEgASgLMhwuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNBIrYBCh1TZXRPcGVyYXRvckNBQ1JMU291cmNlUmVxdWVzdBIOCgZzaGEyNTYYASABKAkSDQoDdXJsGAIgASgJSAASDgoEbm9uZRgDIAEoCEgAEhEKB2NybF9kZXIYBSABKAxIABJFChBhY2tub3dsZWRnZW1lbnRzGAQgAygOMisuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNBQWNrbm93bGVkZ2VtZW50QgwKCmNybF9zb3VyY2UiUwoeU2V0T3BlcmF0b3JDQUNSTFNvdXJjZVJlc3BvbnNlEjEKC29wZXJhdG9yX2NhGAEgASgLMhwuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNBIjsKGFVwbG9hZE9wZXJhdG9yQ1JMUmVxdWVzdBIOCgZzaGEyNTYYASABKAkSDwoHY3JsX2RlchgCIAEoDCJOChlVcGxvYWRPcGVyYXRvckNSTFJlc3BvbnNlEjEKC29wZXJhdG9yX2NhGAEgASgLMhwuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNBImsKGFNldE9wZXJhdG9yQ0FPQ1NQUmVxdWVzdBIOCgZzaGEyNTYYASABKAkSLQoJb2NzcF9tb2RlGAIgASgOMhouY3J5cHRvcy5mbGVldC52MS5PY3NwTW9kZRIQCghvY3NwX3VybBgDIAEoCSKFAQoZU2V0T3BlcmF0b3JDQU9DU1BSZXNwb25zZRIxCgtvcGVyYXRvcl9jYRgBIAEoCzIcLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JDQRI1CgpvY3NwX3Byb2JlGAIgASgLMiEuY3J5cHRvcy5mbGVldC52MS5PY3NwUHJvYmVSZXN1bHQiKgoWUHJldmlld0Fkb3B0aW9uUmVxdWVzdBIQCghlbmRwb2ludBgBIAEoCSI/ChdQcmV2aWV3QWRvcHRpb25SZXNwb25zZRITCgtjZXJ0X3NoYTI1NhgBIAEoCRIPCgdzdWJqZWN0GAIgASgJIkcKF0xpc3RJbnN0YWxsRGlza3NSZXF1ZXN0EhAKCGVuZHBvaW50GAEgASgJEhoKEnBpbm5lZF9jZXJ0X3NoYTI1NhgCIAEoCSJHChhMaXN0SW5zdGFsbERpc2tzUmVzcG9uc2USKwoFZGlza3MYASADKAsyHC5jcnlwdG9zLm5vZGUudjEuSW5zdGFsbERpc2sicAoQQWRvcHROb2RlUmVxdWVzdBIQCghlbmRwb2ludBgBIAEoCRIaChJwaW5uZWRfY2VydF9zaGEyNTYYAiABKAkSLgoGY29uZmlnGAMgASgLMh4uY3J5cHRvcy5ub2RlLnYxLk1hY2hpbmVDb25maWcihQEKEUFkb3B0Tm9kZVJlc3BvbnNlEg0KBXBoYXNlGAEgASgJEg4KBmRldGFpbBgCIAEoCRIMCgRkb25lGAMgASgIEg8KB25vZGVfaWQYBCABKAkSEwoLYWRvcHRpb25faWQYBSABKAkSHQoVcHJlc2VudGVkX2NlcnRfc2hhMjU2GAYgASgJIk0KIUNvbmZpcm1BZG9wdGlvbkZpbmdlcnByaW50UmVxdWVzdBITCgthZG9wdGlvbl9pZBgBIAEoCRITCgtjZXJ0X3NoYTI1NhgCIAEoCSIkCiJDb25maXJtQWRvcHRpb25GaW5nZXJwcmludFJlc3BvbnNlIloKF0RlY29tbWlzc2lvbk5vZGVSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIbChNjb25maXJtX2NvbW1vbl9uYW1lGAIgASgJEg8KB25vZGVfaWQYAyABKAkiLQoYRGVjb21taXNzaW9uTm9kZVJlc3BvbnNlEhEKCXJlYm9vdGluZxgBIAEoCCJhChFSZWJvb3ROb2RlUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSFQoNY29uZmlybV9jYV9jbhgCIAEoCRIRCglwb3dlcl9vZmYYAyABKAgSDwoHbm9kZV9pZBgEIAEoCSInChJSZWJvb3ROb2RlUmVzcG9uc2USEQoJcmVib290aW5nGAEgASgIIjYKEVJlbmFtZU5vZGVSZXF1ZXN0Eg8KB25vZGVfaWQYASABKAkSEAoIbmV3X25hbWUYAiABKAkiQQoSUmVuYW1lTm9kZVJlc3BvbnNlEisKBG5vZGUYASABKAsyHS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVTdW1tYXJ5IjoKEVJlbW92ZU5vZGVSZXF1ZXN0Eg8KB25vZGVfaWQYASABKAkSFAoMY29uZmlybV9uYW1lGAIgASgJIkEKElJlbW92ZU5vZGVSZXNwb25zZRIrCgRub2RlGAEgASgLMh0uY3J5cHRvcy5mbGVldC52MS5Ob2RlU3VtbWFyeSIhChJMaXN0TWNwS2V5c1JlcXVlc3QSCwoDYWxsGAEgASgIIj4KE0xpc3RNY3BLZXlzUmVzcG9uc2USJwoFaXRlbXMYASADKAsyGC5jcnlwdG9zLmZsZWV0LnYxLk1jcEtleSIhChNSZXZva2VNY3BLZXlSZXF1ZXN0EgoKAmlkGAEgASgJIkEKFFJldm9rZU1jcEtleVJlc3BvbnNlEikKB21jcF9rZXkYASABKAsyGC5jcnlwdG9zLmZsZWV0LnYxLk1jcEtleSI7ChNDcmVhdGVNY3BLZXlSZXF1ZXN0Eg0KBWxhYmVsGAEgASgJEhUKDWxldmVsX2NlaWxpbmcYAiABKAkiWAoUQ3JlYXRlTWNwS2V5UmVzcG9uc2USFQoNcGxhaW50ZXh0X2tleRgBIAEoCRIpCgdtY3Bfa2V5GAIgASgLMhguY3J5cHRvcy5mbGVldC52MS5NY3BLZXkiuwEKBk1jcEtleRIKCgJpZBgBIAEoCRINCgVsYWJlbBgCIAEoCRITCgtjbGllbnRfbmFtZRgDIAEoCRITCgtvcGVyYXRvcl9jbhgEIAEoCRIXCg9vcGVyYXRvcl9zZXJpYWwYBSABKAkSFQoNbGV2ZWxfY2VpbGluZxgGIAEoCRISCgpjcmVhdGVkX2F0GAcgASgJEhQKDGxhc3RfdXNlZF9hdBgIIAEoCRISCgpyZXZva2VkX2F0GAkgASgJIiYKFExpc3RBcHByb3ZhbHNSZXF1ZXN0Eg4KBnN0YXR1cxgBIAEoCSJCChVMaXN0QXBwcm92YWxzUmVzcG9uc2USKQoFaXRlbXMYASADKAsyGi5jcnlwdG9zLmZsZWV0LnYxLkFwcHJvdmFsIjQKFURlY2lkZUFwcHJvdmFsUmVxdWVzdBIKCgJpZBgBIAEoCRIPCgdhcHByb3ZlGAIgASgIIkYKFkRlY2lkZUFwcHJvdmFsUmVzcG9uc2USLAoIYXBwcm92YWwYASABKAsyGi5jcnlwdG9zLmZsZWV0LnYxLkFwcHJvdmFsIrcCCghBcHByb3ZhbBIKCgJpZBgBIAEoCRIMCgR0b29sGAIgASgJEg8KB3N1bW1hcnkYAyABKAkSFgoOcmVxdWVzdF9kaWdlc3QYBCABKAkSFwoPcmVxdWVzdGVkX2J5X2NuGAUgASgJEhsKE3JlcXVlc3RlZF9ieV9zZXJpYWwYBiABKAkSDgoGa2V5X2lkGAcgASgJEhYKDnJlcXVpcmVkX2xldmVsGAggASgJEhIKCmNyZWF0ZWRfYXQYCSABKAkSEgoKZXhwaXJlc19hdBgKIAEoCRIOCgZzdGF0dXMYCyABKAkSFQoNZGVjaWRlZF9ieV9jbhgMIAEoCRIZChFkZWNpZGVkX2J5X3NlcmlhbBgNIAEoCRISCgpkZWNpZGVkX2F0GA4gASgJEgwKBGtpbmQYDyABKAkirwIKEkNlcnRpZmljYXRlUmVxdWVzdBIKCgJpZBgBIAEoCRIUCgxwcm9maWxlX25hbWUYAiABKAkSDwoHY3NyX3BlbRgDIAEoCRIMCgRub3RlGAQgASgJEhcKD3JlcXVlc3RlZF9ieV9jbhgFIAEoCRIbChNyZXF1ZXN0ZWRfYnlfc2VyaWFsGAYgASgJEg0KBXN0YXRlGAcgASgJEhMKC2FwcHJvdmFsX2lkGAggASgJEhcKD2NlcnRpZmljYXRlX3BlbRgJIAEoCRIWCg5mYWlsdXJlX3JlYXNvbhgKIAEoCRISCgpjcmVhdGVkX2F0GAsgASgJEhIKCmV4cGlyZXNfYXQYDCABKAkSEgoKZGVjaWRlZF9hdBgNIAEoCRIRCglpc3N1ZWRfYXQYDiABKAkiVgofQ3JlYXRlQ2VydGlmaWNhdGVSZXF1ZXN0UmVxdWVzdBIUCgxwcm9maWxlX25hbWUYASABKAkSDwoHY3NyX2RlchgCIAEoDBIMCgRub3RlGAMgASgJIlkKIENyZWF0ZUNlcnRpZmljYXRlUmVxdWVzdFJlc3BvbnNlEjUKB3JlcXVlc3QYASABKAsyJC5jcnlwdG9zLmZsZWV0LnYxLkNlcnRpZmljYXRlUmVxdWVzdCJCCh5MaXN0Q2VydGlmaWNhdGVSZXF1ZXN0c1JlcXVlc3QSDQoFc3RhdGUYASABKAkSEQoJbWluZV9vbmx5GAIgASgIIlYKH0xpc3RDZXJ0aWZpY2F0ZVJlcXVlc3RzUmVzcG9uc2USMwoFaXRlbXMYASADKAsyJC5jcnlwdG9zLmZsZWV0LnYxLkNlcnRpZmljYXRlUmVxdWVzdCIuCiBHZXRDZXJ0aWZpY2F0ZVJlcXVlc3RCeUlEUmVxdWVzdBIKCgJpZBgBIAEoCSJaCiFHZXRDZXJ0aWZpY2F0ZVJlcXVlc3RCeUlEUmVzcG9uc2USNQoHcmVxdWVzdBgBIAEoCzIkLmNyeXB0b3MuZmxlZXQudjEuQ2VydGlmaWNhdGVSZXF1ZXN0Ii0KH0NhbmNlbENlcnRpZmljYXRlUmVxdWVzdFJlcXVlc3QSCgoCaWQYASABKAkiWQogQ2FuY2VsQ2VydGlmaWNhdGVSZXF1ZXN0UmVzcG9uc2USNQoHcmVxdWVzdBgBIAEoCzIkLmNyeXB0b3MuZmxlZXQudjEuQ2VydGlmaWNhdGVSZXF1ZXN0IkQKHkxpc3ROb2RlVHNhQ2VydGlmaWNhdGVzUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSDwoHbm9kZV9pZBgCIAEoCSKGAQoSTm9kZVRzYUNlcnRpZmljYXRlEhAKCGNlcnRfcGVtGAEgASgJEhIKCnNlcmlhbF9oZXgYAiABKAkSEgoKc2hhMjU2X2hleBgDIAEoCRISCgpub3RfYmVmb3JlGAQgASgJEhEKCW5vdF9hZnRlchgFIAEoCRIPCgdjdXJyZW50GAYgASgIIl0KH0xpc3ROb2RlVHNhQ2VydGlmaWNhdGVzUmVzcG9uc2USOgoMY2VydGlmaWNhdGVzGAEgAygLMiQuY3J5cHRvcy5mbGVldC52MS5Ob2RlVHNhQ2VydGlmaWNhdGUiXgofVmFsaWRhdGVDZXJ0aWZpY2F0ZUNoYWluUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSDwoHbm9kZV9pZBgCIAEoCRIXCg9jZXJ0aWZpY2F0ZV9wZW0YAyABKAkiewogVmFsaWRhdGVDZXJ0aWZpY2F0ZUNoYWluUmVzcG9uc2USDQoFdmFsaWQYASABKAgSDgoGcmVhc29uGAIgASgJEg8KB3N1YmplY3QYAyABKAkSDgoGaXNzdWVyGAQgASgJEhcKD25vZGVfY2Ffc3ViamVjdBgFIAEoCSKuAQoaTGlzdE5vZGVBdWRpdEV2ZW50c1JlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEg8KB25vZGVfaWQYAiABKAkSEQoJcGFnZV9zaXplGAMgASgFEhIKCnBhZ2VfdG9rZW4YBCABKAkSEQoJZnJvbV90aW1lGAUgASgJEg8KB3RvX3RpbWUYBiABKAkSEgoKZXZlbnRfdHlwZRgHIAEoCRINCgVhY3RvchgIIAEoCSKQAgoOTm9kZUF1ZGl0RXZlbnQSCwoDc2VxGAEgASgEEgoKAnRzGAIgASgJEhUKDWFjdG9yX3N1YmplY3QYAyABKAkSEgoKcnBjX21ldGhvZBgEIAEoCRIPCgdvdXRjb21lGAUgASgJEj4KB2RldGFpbHMYBiADKAsyLS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVBdWRpdEV2ZW50LkRldGFpbHNFbnRyeRIYChBlbnRyeV9zaGEyNTZfaGV4GAcgASgJEg4KBnRhcmdldBgIIAEoCRIPCgdzdW1tYXJ5GAkgASgJGi4KDERldGFpbHNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBImkKG0xpc3ROb2RlQXVkaXRFdmVudHNSZXNwb25zZRIxCgdlbnRyaWVzGAEgAygLMiAuY3J5cHRvcy5mbGVldC52MS5Ob2RlQXVkaXRFdmVudBIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkiQQobVmVyaWZ5Tm9kZUF1ZGl0Q2hhaW5SZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJInIKHFZlcmlmeU5vZGVBdWRpdENoYWluUmVzcG9uc2USEwoLZW50cnlfY291bnQYASABKAQSDgoGaW50YWN0GAIgASgIEh0KFWZpcnN0X2Jyb2tlbl9zZXF1ZW5jZRgDIAEoBBIOCgZyZWFzb24YBCABKAkiPwoZR2V0Tm9kZUltYWdlU3RhdHVzUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSDwoHbm9kZV9pZBgCIAEoCSKKAQoPTm9kZUltYWdlU3RhdHVzEhYKDnJ1bm5pbmdfc2hhMjU2GAEgASgJEhUKDWFjdGl2ZV9zaGEyNTYYAiABKAkSFwoPcHJldmlvdXNfc2hhMjU2GAMgASgJEhYKDnJlYm9vdF9wZW5kaW5nGAQgASgIEhcKD3J1bm5pbmdfdmVyc2lvbhgFIAEoCSJPChpHZXROb2RlSW1hZ2VTdGF0dXNSZXNwb25zZRIxCgZzdGF0dXMYASABKAsyIS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVJbWFnZVN0YXR1cyJxChVTdGFnZU5vZGVJbWFnZVJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEg8KB25vZGVfaWQYAiABKAkSEQoJaW1hZ2VfdXJsGAMgASgJEhEKCXNpZ25hdHVyZRgEIAEoDBIOCgZzaGEyNTYYBSABKAkiZAoWU3RhZ2VOb2RlSW1hZ2VSZXNwb25zZRIxCgZzdGF0dXMYASABKAsyIS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVJbWFnZVN0YXR1cxIXCg9yZXF1aXJlc19yZWJvb3QYAiABKAgiVQoYQWN0aXZhdGVOb2RlSW1hZ2VSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJEhUKDWNvbmZpcm1fY2FfY24YAyABKAkiLgoZQWN0aXZhdGVOb2RlSW1hZ2VSZXNwb25zZRIRCglyZWJvb3RpbmcYASABKAgiPgoYUm9sbGJhY2tOb2RlSW1hZ2VSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJImcKGVJvbGxiYWNrTm9kZUltYWdlUmVzcG9uc2USMQoGc3RhdHVzGAEgASgLMiEuY3J5cHRvcy5mbGVldC52MS5Ob2RlSW1hZ2VTdGF0dXMSFwoPcmVxdWlyZXNfcmVib290GAIgASgIIoQBChFOb2RlU2NlcENoYWxsZW5nZRIKCgJpZBgBIAEoCRIPCgdwcm9maWxlGAIgASgJEhMKC2JvdW5kX25hbWVzGAMgAygJEhIKCmNyZWF0ZWRfYXQYBCABKAkSEgoKZXhwaXJlc19hdBgFIAEoCRIVCg1jcmVhdGVkX2J5X2NuGAYgASgJIn0KHE1pbnROb2RlU2NlcENoYWxsZW5nZVJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEg8KB25vZGVfaWQYAiABKAkSDwoHcHJvZmlsZRgDIAEoCRITCgt0dGxfc2Vjb25kcxgEIAEoDRITCgtib3VuZF9uYW1lcxgFIAMoCSJzCh1NaW50Tm9kZVNjZXBDaGFsbGVuZ2VSZXNwb25zZRIaChJjaGFsbGVuZ2VfcGFzc3dvcmQYASABKAkSNgoJY2hhbGxlbmdlGAIgASgLMiMuY3J5cHRvcy5mbGVldC52MS5Ob2RlU2NlcENoYWxsZW5nZSJDCh1MaXN0Tm9kZVNjZXBDaGFsbGVuZ2VzUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSDwoHbm9kZV9pZBgCIAEoCSJZCh5MaXN0Tm9kZVNjZXBDaGFsbGVuZ2VzUmVzcG9uc2USNwoKY2hhbGxlbmdlcxgBIAMoCzIjLmNyeXB0b3MuZmxlZXQudjEuTm9kZVNjZXBDaGFsbGVuZ2UiUAoeUmV2b2tlTm9kZVNjZXBDaGFsbGVuZ2VSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJEgoKAmlkGAMgASgJIlkKH1Jldm9rZU5vZGVTY2VwQ2hhbGxlbmdlUmVzcG9uc2USNgoJY2hhbGxlbmdlGAEgASgLMiMuY3J5cHRvcy5mbGVldC52MS5Ob2RlU2NlcENoYWxsZW5nZSpSCgZIZWFsdGgSFgoSSEVBTFRIX1VOU1BFQ0lGSUVEEAASDQoJSEVBTFRIX1VQEAESDwoLSEVBTFRIX0RPV04QAhIQCgxIRUFMVEhfRVJST1IQAzK0OQoMRmxlZXRTZXJ2aWNlElQKCUxpc3ROb2RlcxIiLmNyeXB0b3MuZmxlZXQudjEuTGlzdE5vZGVzUmVxdWVzdBojLmNyeXB0b3MuZmxlZXQudjEuTGlzdE5vZGVzUmVzcG9uc2USTgoHR2V0Tm9kZRIgLmNyeXB0b3MuZmxlZXQudjEuR2V0Tm9kZVJlcXVlc3QaIS5jcnlwdG9zLmZsZWV0LnYxLkdldE5vZGVSZXNwb25zZRJpChBMaXN0Q2VydGlmaWNhdGVzEikuY3J5cHRvcy5mbGVldC52MS5MaXN0Q2VydGlmaWNhdGVzUmVxdWVzdBoqLmNyeXB0b3MuZmxlZXQudjEuTGlzdENlcnRpZmljYXRlc1Jlc3BvbnNlEl0KDExpc3RQcm9maWxlcxIlLmNyeXB0b3MuZmxlZXQudjEuTGlzdFByb2ZpbGVzUmVxdWVzdBomLmNyeXB0b3MuZmxlZXQudjEuTGlzdFByb2ZpbGVzUmVzcG9uc2USYAoNQ3JlYXRlUHJvZmlsZRImLmNyeXB0b3MuZmxlZXQudjEuQ3JlYXRlUHJvZmlsZVJlcXVlc3QaJy5jcnlwdG9zLmZsZWV0LnYxLkNyZWF0ZVByb2ZpbGVSZXNwb25zZRJgCg1VcGRhdGVQcm9maWxlEiYuY3J5cHRvcy5mbGVldC52MS5VcGRhdGVQcm9maWxlUmVxdWVzdBonLmNyeXB0b3MuZmxlZXQudjEuVXBkYXRlUHJvZmlsZVJlc3BvbnNlEmAKDURlbGV0ZVByb2ZpbGUSJi5jcnlwdG9zLmZsZWV0LnYxLkRlbGV0ZVByb2ZpbGVSZXF1ZXN0GicuY3J5cHRvcy5mbGVldC52MS5EZWxldGVQcm9maWxlUmVzcG9uc2USbwoSQXBwbHlQcm9maWxlVG9Ob2RlEisuY3J5cHRvcy5mbGVldC52MS5BcHBseVByb2ZpbGVUb05vZGVSZXF1ZXN0GiwuY3J5cHRvcy5mbGVldC52MS5BcHBseVByb2ZpbGVUb05vZGVSZXNwb25zZRJ4ChVTZXRQcm9maWxlUmVxdWVzdGFibGUSLi5jcnlwdG9zLmZsZWV0LnYxLlNldFByb2ZpbGVSZXF1ZXN0YWJsZVJlcXVlc3QaLy5jcnlwdG9zLmZsZWV0LnYxLlNldFByb2ZpbGVSZXF1ZXN0YWJsZVJlc3BvbnNlEn4KF0xpc3RSZXF1ZXN0YWJsZVByb2ZpbGVzEjAuY3J5cHRvcy5mbGVldC52MS5MaXN0UmVxdWVzdGFibGVQcm9maWxlc1JlcXVlc3QaMS5jcnlwdG9zLmZsZWV0LnYxLkxpc3RSZXF1ZXN0YWJsZVByb2ZpbGVzUmVzcG9uc2USXQoMTGlzdEFkYXB0ZXJzEiUuY3J5cHRvcy5mbGVldC52MS5MaXN0QWRhcHRlcnNSZXF1ZXN0GiYuY3J5cHRvcy5mbGVldC52MS5MaXN0QWRhcHRlcnNSZXNwb25zZRJsChFTZXRBZGFwdGVyRW5hYmxlZBIqLmNyeXB0b3MuZmxlZXQudjEuU2V0QWRhcHRlckVuYWJsZWRSZXF1ZXN0GisuY3J5cHRvcy5mbGVldC52MS5TZXRBZGFwdGVyRW5hYmxlZFJlc3BvbnNlEmYKD1NldE5vZGVQcm90b2NvbBIoLmNyeXB0b3MuZmxlZXQudjEuU2V0Tm9kZVByb3RvY29sUmVxdWVzdBopLmNyeXB0b3MuZmxlZXQudjEuU2V0Tm9kZVByb3RvY29sUmVzcG9uc2USVAoJTGlzdEF1ZGl0EiIuY3J5cHRvcy5mbGVldC52MS5MaXN0QXVkaXRSZXF1ZXN0GiMuY3J5cHRvcy5mbGVldC52MS5MaXN0QXVkaXRSZXNwb25zZRJmCg9MaXN0RW5yb2xsbWVudHMSKC5jcnlwdG9zLmZsZWV0LnYxLkxpc3RFbnJvbGxtZW50c1JlcXVlc3QaKS5jcnlwdG9zLmZsZWV0LnYxLkxpc3RFbnJvbGxtZW50c1Jlc3BvbnNlEmkKEENyZWF0ZUVucm9sbG1lbnQSKS5jcnlwdG9zLmZsZWV0LnYxLkNyZWF0ZUVucm9sbG1lbnRSZXF1ZXN0GiouY3J5cHRvcy5mbGVldC52MS5DcmVhdGVFbnJvbGxtZW50UmVzcG9uc2USbAoRQXBwcm92ZUVucm9sbG1lbnQSKi5jcnlwdG9zLmZsZWV0LnYxLkFwcHJvdmVFbnJvbGxtZW50UmVxdWVzdBorLmNyeXB0b3MuZmxlZXQudjEuQXBwcm92ZUVucm9sbG1lbnRSZXNwb25zZRJpChBSZWplY3RFbnJvbGxtZW50EikuY3J5cHRvcy5mbGVldC52MS5SZWplY3RFbnJvbGxtZW50UmVxdWVzdBoqLmNyeXB0b3MuZmxlZXQudjEuUmVqZWN0RW5yb2xsbWVudFJlc3BvbnNlEksKBldob0FtSRIfLmNyeXB0b3MuZmxlZXQudjEuV2hvQW1JUmVxdWVzdBogLmNyeXB0b3MuZmxlZXQudjEuV2hvQW1JUmVzcG9uc2USbAoRUmV2b2tlQ2VydGlmaWNhdGUSKi5jcnlwdG9zLmZsZWV0LnYxLlJldm9rZUNlcnRpZmljYXRlUmVxdWVzdBorLmNyeXB0b3MuZmxlZXQudjEuUmV2b2tlQ2VydGlmaWNhdGVSZXNwb25zZRJjCg5HZXRDZXJ0aWZpY2F0ZRInLmNyeXB0b3MuZmxlZXQudjEuR2V0Q2VydGlmaWNhdGVSZXF1ZXN0GiguY3J5cHRvcy5mbGVldC52MS5HZXRDZXJ0aWZpY2F0ZVJlc3BvbnNlEnIKE0xpc3ROb2RlQXVkaXRFdmVudHMSLC5jcnlwdG9zLmZsZWV0LnYxLkxpc3ROb2RlQXVkaXRFdmVudHNSZXF1ZXN0Gi0uY3J5cHRvcy5mbGVldC52MS5MaXN0Tm9kZUF1ZGl0RXZlbnRzUmVzcG9uc2USdQoUVmVyaWZ5Tm9kZUF1ZGl0Q2hhaW4SLS5jcnlwdG9zLmZsZWV0LnYxLlZlcmlmeU5vZGVBdWRpdENoYWluUmVxdWVzdBouLmNyeXB0b3MuZmxlZXQudjEuVmVyaWZ5Tm9kZUF1ZGl0Q2hhaW5SZXNwb25zZRKBAQoYVmFsaWRhdGVDZXJ0aWZpY2F0ZUNoYWluEjEuY3J5cHRvcy5mbGVldC52MS5WYWxpZGF0ZUNlcnRpZmljYXRlQ2hhaW5SZXF1ZXN0GjIuY3J5cHRvcy5mbGVldC52MS5WYWxpZGF0ZUNlcnRpZmljYXRlQ2hhaW5SZXNwb25zZRJ+ChdMaXN0Tm9kZVRzYUNlcnRpZmljYXRlcxIwLmNyeXB0b3MuZmxlZXQudjEuTGlzdE5vZGVUc2FDZXJ0aWZpY2F0ZXNSZXF1ZXN0GjEuY3J5cHRvcy5mbGVldC52MS5MaXN0Tm9kZVRzYUNlcnRpZmljYXRlc1Jlc3BvbnNlEm8KEkdldE5vZGVJbWFnZVN0YXR1cxIrLmNyeXB0b3MuZmxlZXQudjEuR2V0Tm9kZUltYWdlU3RhdHVzUmVxdWVzdBosLmNyeXB0b3MuZmxlZXQudjEuR2V0Tm9kZUltYWdlU3RhdHVzUmVzcG9uc2USYwoOU3RhZ2VOb2RlSW1hZ2USJy5jcnlwdG9zLmZsZWV0LnYxLlN0YWdlTm9kZUltYWdlUmVxdWVzdBooLmNyeXB0b3MuZmxlZXQudjEuU3RhZ2VOb2RlSW1hZ2VSZXNwb25zZRJsChFBY3RpdmF0ZU5vZGVJbWFnZRIqLmNyeXB0b3MuZmxlZXQudjEuQWN0aXZhdGVOb2RlSW1hZ2VSZXF1ZXN0GisuY3J5cHRvcy5mbGVldC52MS5BY3RpdmF0ZU5vZGVJbWFnZVJlc3BvbnNlEmwKEVJvbGxiYWNrTm9kZUltYWdlEiouY3J5cHRvcy5mbGVldC52MS5Sb2xsYmFja05vZGVJbWFnZVJlcXVlc3QaKy5jcnlwdG9zLmZsZWV0LnYxLlJvbGxiYWNrTm9kZUltYWdlUmVzcG9uc2USVAoJSXNzdWVMZWFmEiIuY3J5cHRvcy5mbGVldC52MS5Jc3N1ZUxlYWZSZXF1ZXN0GiMuY3J5cHRvcy5mbGVldC52MS5Jc3N1ZUxlYWZSZXNwb25zZRJUCglSZWtleU5vZGUSIi5jcnlwdG9zLmZsZWV0LnYxLlJla2V5Tm9kZVJlcXVlc3QaIy5jcnlwdG9zLmZsZWV0LnYxLlJla2V5Tm9kZVJlc3BvbnNlEmAKDUdldE5vZGVDb25maWcSJi5jcnlwdG9zLmZsZWV0LnYxLkdldE5vZGVDb25maWdSZXF1ZXN0GicuY3J5cHRvcy5mbGVldC52MS5HZXROb2RlQ29uZmlnUmVzcG9uc2USZgoPQXBwbHlOb2RlQ29uZmlnEiguY3J5cHRvcy5mbGVldC52MS5BcHBseU5vZGVDb25maWdSZXF1ZXN0GikuY3J5cHRvcy5mbGVldC52MS5BcHBseU5vZGVDb25maWdSZXNwb25zZRJaCgtFeHBvcnRDQUtleRIkLmNyeXB0b3MuZmxlZXQudjEuRXhwb3J0Q0FLZXlSZXF1ZXN0GiUuY3J5cHRvcy5mbGVldC52MS5FeHBvcnRDQUtleVJlc3BvbnNlEloKC0ltcG9ydENBS2V5EiQuY3J5cHRvcy5mbGVldC52MS5JbXBvcnRDQUtleVJlcXVlc3QaJS5jcnlwdG9zLmZsZWV0LnYxLkltcG9ydENBS2V5UmVzcG9uc2USlgEKH0NyZWF0ZU9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3QSOC5jcnlwdG9zLmZsZWV0LnYxLkNyZWF0ZU9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3RSZXF1ZXN0GjkuY3J5cHRvcy5mbGVldC52MS5DcmVhdGVPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0UmVzcG9uc2USkwEKHkxpc3RPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0cxI3LmNyeXB0b3MuZmxlZXQudjEuTGlzdE9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3RzUmVxdWVzdBo4LmNyeXB0b3MuZmxlZXQudjEuTGlzdE9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3RzUmVzcG9uc2USlgEKH0NhbmNlbE9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3QSOC5jcnlwdG9zLmZsZWV0LnYxLkNhbmNlbE9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3RSZXF1ZXN0GjkuY3J5cHRvcy5mbGVldC52MS5DYW5jZWxPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0UmVzcG9uc2USgQEKGFJlY29yZE9wZXJhdG9yQ3JlZGVudGlhbBIxLmNyeXB0b3MuZmxlZXQudjEuUmVjb3JkT3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdBoyLmNyeXB0b3MuZmxlZXQudjEuUmVjb3JkT3BlcmF0b3JDcmVkZW50aWFsUmVzcG9uc2USgQEKGFJldm9rZU9wZXJhdG9yQ3JlZGVudGlhbBIxLmNyeXB0b3MuZmxlZXQudjEuUmV2b2tlT3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdBoyLmNyeXB0b3MuZmxlZXQudjEuUmV2b2tlT3BlcmF0b3JDcmVkZW50aWFsUmVzcG9uc2USfgoXTGlzdE9wZXJhdG9yQ3JlZGVudGlhbHMSMC5jcnlwdG9zLmZsZWV0LnYxLkxpc3RPcGVyYXRvckNyZWRlbnRpYWxzUmVxdWVzdBoxLmNyeXB0b3MuZmxlZXQudjEuTGlzdE9wZXJhdG9yQ3JlZGVudGlhbHNSZXNwb25zZRJmCg9MaXN0T3BlcmF0b3JDQXMSKC5jcnlwdG9zLmZsZWV0LnYxLkxpc3RPcGVyYXRvckNBc1JlcXVlc3QaKS5jcnlwdG9zLmZsZWV0LnYxLkxpc3RPcGVyYXRvckNBc1Jlc3BvbnNlEm8KElJlZ2lzdGVyT3BlcmF0b3JDQRIrLmNyeXB0b3MuZmxlZXQudjEuUmVnaXN0ZXJPcGVyYXRvckNBUmVxdWVzdBosLmNyeXB0b3MuZmxlZXQudjEuUmVnaXN0ZXJPcGVyYXRvckNBUmVzcG9uc2USaQoQUmV0aXJlT3BlcmF0b3JDQRIpLmNyeXB0b3MuZmxlZXQudjEuUmV0aXJlT3BlcmF0b3JDQVJlcXVlc3QaKi5jcnlwdG9zLmZsZWV0LnYxLlJldGlyZU9wZXJhdG9yQ0FSZXNwb25zZRJ7ChZTZXRPcGVyYXRvckNBQ1JMU291cmNlEi8uY3J5cHRvcy5mbGVldC52MS5TZXRPcGVyYXRvckNBQ1JMU291cmNlUmVxdWVzdBowLmNyeXB0b3MuZmxlZXQudjEuU2V0T3BlcmF0b3JDQUNSTFNvdXJjZVJlc3BvbnNlEmwKEVVwbG9hZE9wZXJhdG9yQ1JMEiouY3J5cHRvcy5mbGVldC52MS5VcGxvYWRPcGVyYXRvckNSTFJlcXVlc3QaKy5jcnlwdG9zLmZsZWV0LnYxLlVwbG9hZE9wZXJhdG9yQ1JMUmVzcG9uc2USbAoRU2V0T3BlcmF0b3JDQU9DU1ASKi5jcnlwdG9zLmZsZWV0LnYxLlNldE9wZXJhdG9yQ0FPQ1NQUmVxdWVzdBorLmNyeXB0b3MuZmxlZXQudjEuU2V0T3BlcmF0b3JDQU9DU1BSZXNwb25zZRJmCg9QcmV2aWV3QWRvcHRpb24SKC5jcnlwdG9zLmZsZWV0LnYxLlByZXZpZXdBZG9wdGlvblJlcXVlc3QaKS5jcnlwdG9zLmZsZWV0LnYxLlByZXZpZXdBZG9wdGlvblJlc3BvbnNlEmkKEExpc3RJbnN0YWxsRGlza3MSKS5jcnlwdG9zLmZsZWV0LnYxLkxpc3RJbnN0YWxsRGlza3NSZXF1ZXN0GiouY3J5cHRvcy5mbGVldC52MS5MaXN0SW5zdGFsbERpc2tzUmVzcG9uc2USVgoJQWRvcHROb2RlEiIuY3J5cHRvcy5mbGVldC52MS5BZG9wdE5vZGVSZXF1ZXN0GiMuY3J5cHRvcy5mbGVldC52MS5BZG9wdE5vZGVSZXNwb25zZTABEocBChpDb25maXJtQWRvcHRpb25GaW5nZXJwcmludBIzLmNyeXB0b3MuZmxlZXQudjEuQ29uZmlybUFkb3B0aW9uRmluZ2VycHJpbnRSZXF1ZXN0GjQuY3J5cHRvcy5mbGVldC52MS5Db25maXJtQWRvcHRpb25GaW5nZXJwcmludFJlc3BvbnNlEmkKEERlY29tbWlzc2lvbk5vZGUSKS5jcnlwdG9zLmZsZWV0LnYxLkRlY29tbWlzc2lvbk5vZGVSZXF1ZXN0GiouY3J5cHRvcy5mbGVldC52MS5EZWNvbW1pc3Npb25Ob2RlUmVzcG9uc2USVwoKUmVib290Tm9kZRIjLmNyeXB0b3MuZmxlZXQudjEuUmVib290Tm9kZVJlcXVlc3QaJC5jcnlwdG9zLmZsZWV0LnYxLlJlYm9vdE5vZGVSZXNwb25zZRJXCgpSZW5hbWVOb2RlEiMuY3J5cHRvcy5mbGVldC52MS5SZW5hbWVOb2RlUmVxdWVzdBokLmNyeXB0b3MuZmxlZXQudjEuUmVuYW1lTm9kZVJlc3BvbnNlElcKClJlbW92ZU5vZGUSIy5jcnlwdG9zLmZsZWV0LnYxLlJlbW92ZU5vZGVSZXF1ZXN0GiQuY3J5cHRvcy5mbGVldC52MS5SZW1vdmVOb2RlUmVzcG9uc2USWgoLTGlzdE1jcEtleXMSJC5jcnlwdG9zLmZsZWV0LnYxLkxpc3RNY3BLZXlzUmVxdWVzdBolLmNyeXB0b3MuZmxlZXQudjEuTGlzdE1jcEtleXNSZXNwb25zZRJdCgxSZXZva2VNY3BLZXkSJS5jcnlwdG9zLmZsZWV0LnYxLlJldm9rZU1jcEtleVJlcXVlc3QaJi5jcnlwdG9zLmZsZWV0LnYxLlJldm9rZU1jcEtleVJlc3BvbnNlEl0KDENyZWF0ZU1jcEtleRIlLmNyeXB0b3MuZmxlZXQudjEuQ3JlYXRlTWNwS2V5UmVxdWVzdBomLmNyeXB0b3MuZmxlZXQudjEuQ3JlYXRlTWNwS2V5UmVzcG9uc2USYAoNTGlzdEFwcHJvdmFscxImLmNyeXB0b3MuZmxlZXQudjEuTGlzdEFwcHJvdmFsc1JlcXVlc3QaJy5jcnlwdG9zLmZsZWV0LnYxLkxpc3RBcHByb3ZhbHNSZXNwb25zZRJjCg5EZWNpZGVBcHByb3ZhbBInLmNyeXB0b3MuZmxlZXQudjEuRGVjaWRlQXBwcm92YWxSZXF1ZXN0GiguY3J5cHRvcy5mbGVldC52MS5EZWNpZGVBcHByb3ZhbFJlc3BvbnNlEoEBChhDcmVhdGVDZXJ0aWZpY2F0ZVJlcXVlc3QSMS5jcnlwdG9zLmZsZWV0LnYxLkNyZWF0ZUNlcnRpZmljYXRlUmVxdWVzdFJlcXVlc3QaMi5jcnlwdG9zLmZsZWV0LnYxLkNyZWF0ZUNlcnRpZmljYXRlUmVxdWVzdFJlc3BvbnNlEn4KF0xpc3RDZXJ0aWZpY2F0ZVJlcXVlc3RzEjAuY3J5cHRvcy5mbGVldC52MS5MaXN0Q2VydGlmaWNhdGVSZXF1ZXN0c1JlcXVlc3QaMS5jcnlwdG9zLmZsZWV0LnYxLkxpc3RDZXJ0aWZpY2F0ZVJlcXVlc3RzUmVzcG9uc2UShAEKGUdldENlcnRpZmljYXRlUmVxdWVzdEJ5SUQSMi5jcnlwdG9zLmZsZWV0LnYxLkdldENlcnRpZmljYXRlUmVxdWVzdEJ5SURSZXF1ZXN0GjMuY3J5cHRvcy5mbGVldC52MS5HZXRDZXJ0aWZpY2F0ZVJlcXVlc3RCeUlEUmVzcG9uc2USgQEKGENhbmNlbENlcnRpZmljYXRlUmVxdWVzdBIxLmNyeXB0b3MuZmxlZXQudjEuQ2FuY2VsQ2VydGlmaWNhdGVSZXF1ZXN0UmVxdWVzdBoyLmNyeXB0b3MuZmxlZXQudjEuQ2FuY2VsQ2VydGlmaWNhdGVSZXF1ZXN0UmVzcG9uc2USeAoVTWludE5vZGVTY2VwQ2hhbGxlbmdlEi4uY3J5cHRvcy5mbGVldC52MS5NaW50Tm9kZVNjZXBDaGFsbGVuZ2VSZXF1ZXN0Gi8uY3J5cHRvcy5mbGVldC52MS5NaW50Tm9kZVNjZXBDaGFsbGVuZ2VSZXNwb25zZRJ7ChZMaXN0Tm9kZVNjZXBDaGFsbGVuZ2VzEi8uY3J5cHRvcy5mbGVldC52MS5MaXN0Tm9kZVNjZXBDaGFsbGVuZ2VzUmVxdWVzdBowLmNyeXB0b3MuZmxlZXQudjEuTGlzdE5vZGVTY2VwQ2hhbGxlbmdlc1Jlc3BvbnNlEn4KF1Jldm9rZU5vZGVTY2VwQ2hhbGxlbmdlEjAuY3J5cHRvcy5mbGVldC52MS5SZXZva2VOb2RlU2NlcENoYWxsZW5nZVJlcXVlc3QaMS5jcnlwdG9zLmZsZWV0LnYxLlJldm9rZU5vZGVTY2VwQ2hhbGxlbmdlUmVzcG9uc2VCSFpGZ2l0aHViLmNvbS9DcnlwdE9TLVBLSS9jcnlwdG9zLW1hbmFnZXIvZ2VuL2dvL2NyeXB0b3MvZmxlZXQvdjE7ZmxlZXR2MWIGcHJvdG8z", [file_cryptos_fleet_v1_operator_ca, file_cryptos_node_v1_config, file_cryptos_node_v1_node, file_cryptos_node_v1_status]); + fileDesc("ChxjcnlwdG9zL2ZsZWV0L3YxL2ZsZWV0LnByb3RvEhBjcnlwdG9zLmZsZWV0LnYxIhIKEExpc3ROb2Rlc1JlcXVlc3QiQQoRTGlzdE5vZGVzUmVzcG9uc2USLAoFbm9kZXMYASADKAsyHS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVTdW1tYXJ5Ii8KDkdldE5vZGVSZXF1ZXN0EgwKBG5hbWUYASABKAkSDwoHbm9kZV9pZBgCIAEoCSI9Cg9HZXROb2RlUmVzcG9uc2USKgoEbm9kZRgBIAEoCzIcLmNyeXB0b3MuZmxlZXQudjEuTm9kZURldGFpbCI4ChdMaXN0Q2VydGlmaWNhdGVzUmVxdWVzdBIMCgRub2RlGAEgASgJEg8KB25vZGVfaWQYAiABKAkiTwoYTGlzdENlcnRpZmljYXRlc1Jlc3BvbnNlEjMKDGNlcnRpZmljYXRlcxgBIAMoCzIdLmNyeXB0b3MuZmxlZXQudjEuQ2VydGlmaWNhdGUiFQoTTGlzdFByb2ZpbGVzUmVxdWVzdCJKChRMaXN0UHJvZmlsZXNSZXNwb25zZRIyCgVpdGVtcxgBIAMoCzIjLmNyeXB0b3Mubm9kZS52MS5DZXJ0aWZpY2F0ZVByb2ZpbGUiTAoUQ3JlYXRlUHJvZmlsZVJlcXVlc3QSNAoHcHJvZmlsZRgBIAEoCzIjLmNyeXB0b3Mubm9kZS52MS5DZXJ0aWZpY2F0ZVByb2ZpbGUiFwoVQ3JlYXRlUHJvZmlsZVJlc3BvbnNlIkwKFFVwZGF0ZVByb2ZpbGVSZXF1ZXN0EjQKB3Byb2ZpbGUYASABKAsyIy5jcnlwdG9zLm5vZGUudjEuQ2VydGlmaWNhdGVQcm9maWxlIhcKFVVwZGF0ZVByb2ZpbGVSZXNwb25zZSIkChREZWxldGVQcm9maWxlUmVxdWVzdBIMCgRuYW1lGAEgASgJIhcKFURlbGV0ZVByb2ZpbGVSZXNwb25zZSJVChlBcHBseVByb2ZpbGVUb05vZGVSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIUCgxwcm9maWxlX25hbWUYAiABKAkSDwoHbm9kZV9pZBgDIAEoCSJJChpBcHBseVByb2ZpbGVUb05vZGVSZXNwb25zZRISCgpnZW5lcmF0aW9uGAEgASgEEhcKD3JlcXVpcmVzX3JlYm9vdBgCIAEoCCJBChxTZXRQcm9maWxlUmVxdWVzdGFibGVSZXF1ZXN0EgwKBG5hbWUYASABKAkSEwoLcmVxdWVzdGFibGUYAiABKAgiHwodU2V0UHJvZmlsZVJlcXVlc3RhYmxlUmVzcG9uc2UiIAoeTGlzdFJlcXVlc3RhYmxlUHJvZmlsZXNSZXF1ZXN0IlUKH0xpc3RSZXF1ZXN0YWJsZVByb2ZpbGVzUmVzcG9uc2USMgoFaXRlbXMYASADKAsyIy5jcnlwdG9zLm5vZGUudjEuQ2VydGlmaWNhdGVQcm9maWxlIhUKE0xpc3RBZGFwdGVyc1JlcXVlc3QiSgoUTGlzdEFkYXB0ZXJzUmVzcG9uc2USMgoFaXRlbXMYASADKAsyIy5jcnlwdG9zLmZsZWV0LnYxLkVucm9sbG1lbnRBZGFwdGVyIjkKGFNldEFkYXB0ZXJFbmFibGVkUmVxdWVzdBIMCgRuYW1lGAEgASgJEg8KB2VuYWJsZWQYAiABKAgiUQoZU2V0QWRhcHRlckVuYWJsZWRSZXNwb25zZRI0CgdhZGFwdGVyGAEgASgLMiMuY3J5cHRvcy5mbGVldC52MS5FbnJvbGxtZW50QWRhcHRlciISChBMaXN0QXVkaXRSZXF1ZXN0IkAKEUxpc3RBdWRpdFJlc3BvbnNlEisKBWl0ZW1zGAEgAygLMhwuY3J5cHRvcy5mbGVldC52MS5BdWRpdEV2ZW50IhgKFkxpc3RFbnJvbGxtZW50c1JlcXVlc3QiTQoXTGlzdEVucm9sbG1lbnRzUmVzcG9uc2USMgoFaXRlbXMYASADKAsyIy5jcnlwdG9zLmZsZWV0LnYxLkVucm9sbG1lbnRSZXF1ZXN0IogCCgtOb2RlU3VtbWFyeRIMCgRuYW1lGAEgASgJEg8KB2FkZHJlc3MYAiABKAkSDAoEcm9sZRgDIAEoCRIWCg5pZGVudGl0eV9zdGF0ZRgEIAEoCRIKCgJjbhgFIAEoCRIOCgZpc3N1ZXIYBiABKAkSKAoGaGVhbHRoGAcgASgOMhguY3J5cHRvcy5mbGVldC52MS5IZWFsdGgSFQoNaGVhbHRoX2RldGFpbBgIIAEoCRIKCgJpZBgJIAEoCRIyCglwcm90b2NvbHMYCiADKAsyHy5jcnlwdG9zLm5vZGUudjEuUHJvdG9jb2xTdGF0dXMSFwoPcmVib290X3JlcXVpcmVkGAsgASgIIkkKDE5vZGVJZGVudGl0eRIRCgljaGFpbl9wZW0YASABKAkSEQoJY2hhaW5fZGVyGAIgAygMEhMKC2xlYWZfc2hhMjU2GAMgASgJIqkBCgpOb2RlRGV0YWlsEi4KB3N1bW1hcnkYASABKAsyHS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVTdW1tYXJ5EjAKCGlkZW50aXR5GAIgASgLMh4uY3J5cHRvcy5mbGVldC52MS5Ob2RlSWRlbnRpdHkSFQoNdHBtX2F2YWlsYWJsZRgDIAEoCBISCgpib290X2NvdW50GAQgASgEEg4KBnVwdGltZRgFIAEoCSLYAQoLQ2VydGlmaWNhdGUSDgoGc2VyaWFsGAEgASgJEhIKCnN1YmplY3RfY24YAiABKAkSEwoLaXNzdWVyX25vZGUYAyABKAkSDAoEa2luZBgEIAEoCRIOCgZzdGF0dXMYBSABKAkSEgoKbm90X2JlZm9yZRgGIAEoCRIRCglub3RfYWZ0ZXIYByABKAkSDwoHcHJvZmlsZRgIIAEoCRISCgpyZXZva2VkX2F0GAkgASgJEg4KBnJlYXNvbhgKIAEoCRIWCg5pc3N1ZXJfbm9kZV9pZBgLIAEoCSKNAQoRRW5yb2xsbWVudEFkYXB0ZXISDAoEa2luZBgBIAEoCRIMCgRuYW1lGAIgASgJEhAKCGVuZHBvaW50GAMgASgJEg8KB3Byb2ZpbGUYBCABKAkSDwoHZW5hYmxlZBgFIAEoCBISCgpjaGFsbGVuZ2VzGAYgAygJEhQKDGdwb190ZW1wbGF0ZRgHIAEoCSK8AgoKQXVkaXRFdmVudBIKCgJpZBgBIAEoCRIKCgJhdBgCIAEoCRIMCgRraW5kGAMgASgJEg8KB3N1bW1hcnkYBCABKAkSEwoLdGFyZ2V0X2tpbmQYBSABKAkSEwoLdGFyZ2V0X3BhdGgYBiABKAkSEgoKYWN0b3Jfa2luZBgHIAEoCRIQCghhY3Rvcl9jbhgIIAEoCRIUCgxhY3Rvcl9zZXJpYWwYCSABKAkSDgoGa2V5X2lkGAogASgJEgsKA3ZpYRgLIAEoCRIMCgR0b29sGAwgASgJEhYKDnJlcXVlc3RfZGlnZXN0GA0gASgJEg8KB291dGNvbWUYDiABKAkSEwoLYXBwcm92YWxfaWQYDyABKAkSFwoPYXBwcm92ZXJfc2VyaWFsGBAgASgJEg8KB25vZGVfaWQYESABKAki7wIKEUVucm9sbG1lbnRSZXF1ZXN0EgoKAmlkGAEgASgJEhUKDXByb3Bvc2VkX25hbWUYAiABKAkSDAoEcm9sZRgDIAEoCRIRCglwYXJlbnRfY24YBCABKAkSDwoHYWRkcmVzcxgFIAEoCRIOCgZzdGF0dXMYBiABKAkSGwoTYXR0ZXN0YXRpb25fc3VtbWFyeRgHIAEoCRIbChNhdHRlc3RhdGlvbl9ub2RlX2lkGAggASgJEhQKDGNzcl9rZXlfdHlwZRgJIAEoCRIWCg5jc3Jfc3ViamVjdF9jbhgKIAEoCRIUCgxyZXF1ZXN0ZWRfYXQYCyABKAkSGAoQcmVqZWN0aW9uX3JlYXNvbhgMIAEoCRIaChJhZG1pdHRlZF9ub2RlX25hbWUYDSABKAkSDAoEa2luZBgOIAEoCRIZChFwaW5uZWRfa2V5X3NoYTI1NhgPIAEoCRIYChBhZG1pdHRlZF9ub2RlX2lkGBAgASgJIswBChdDcmVhdGVFbnJvbGxtZW50UmVxdWVzdBIMCgRraW5kGAEgASgJEhUKDW5vZGVfZW5kcG9pbnQYAiABKAkSFgoOYWRtaW5fY2VydF9wZW0YAyABKAkSFQoNYWRtaW5fa2V5X3BlbRgEIAEoCRIOCgZjYV9wZW0YBSABKAkSEgoKY2hpbGRfbm9kZRgGIAEoCRIRCglwYXJlbnRfY24YByABKAkSDwoHcHJvZmlsZRgIIAEoCRIVCg1jaGlsZF9ub2RlX2lkGAkgASgJIlMKGENyZWF0ZUVucm9sbG1lbnRSZXNwb25zZRI3CgplbnJvbGxtZW50GAEgASgLMiMuY3J5cHRvcy5mbGVldC52MS5FbnJvbGxtZW50UmVxdWVzdCJ8ChhBcHByb3ZlRW5yb2xsbWVudFJlcXVlc3QSCgoCaWQYASABKAkSFQoNbm9kZV9lbmRwb2ludBgCIAEoCRIWCg5hZG1pbl9jZXJ0X3BlbRgDIAEoCRIVCg1hZG1pbl9rZXlfcGVtGAQgASgJEg4KBmNhX3BlbRgFIAEoCSJUChlBcHByb3ZlRW5yb2xsbWVudFJlc3BvbnNlEjcKCmVucm9sbG1lbnQYASABKAsyIy5jcnlwdG9zLmZsZWV0LnYxLkVucm9sbG1lbnRSZXF1ZXN0IjUKF1JlamVjdEVucm9sbG1lbnRSZXF1ZXN0EgoKAmlkGAEgASgJEg4KBnJlYXNvbhgCIAEoCSJTChhSZWplY3RFbnJvbGxtZW50UmVzcG9uc2USNwoKZW5yb2xsbWVudBgBIAEoCzIjLmNyeXB0b3MuZmxlZXQudjEuRW5yb2xsbWVudFJlcXVlc3QiDwoNV2hvQW1JUmVxdWVzdCI9ChBPcGVyYXRvcklkZW50aXR5EgoKAmNuGAEgASgJEg4KBnNlcmlhbBgCIAEoCRINCgVsZXZlbBgDIAEoCSJGCg5XaG9BbUlSZXNwb25zZRI0CghvcGVyYXRvchgBIAEoCzIiLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JJZGVudGl0eSJnChhSZXZva2VDZXJ0aWZpY2F0ZVJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEhIKCnNlcmlhbF9oZXgYAiABKAkSEwoLcmVhc29uX2NvZGUYAyABKAUSDwoHbm9kZV9pZBgEIAEoCSJYChlSZXZva2VDZXJ0aWZpY2F0ZVJlc3BvbnNlEhIKCnNlcmlhbF9oZXgYASABKAkSEgoKcmV2b2tlZF9hdBgCIAEoCRITCgtyZWFzb25fY29kZRgDIAEoBSI+ChVHZXRDZXJ0aWZpY2F0ZVJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEhIKCnNlcmlhbF9oZXgYAiABKAkiaAoWR2V0Q2VydGlmaWNhdGVSZXNwb25zZRIXCg9jZXJ0aWZpY2F0ZV9wZW0YASABKAkSEQoJY2hhaW5fcGVtGAIgASgJEg4KBnN0YXR1cxgDIAEoCRISCgpyZXZva2VkX2F0GAQgASgJIl0KEElzc3VlTGVhZlJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEg8KB2Nzcl9kZXIYAiABKAwSFAoMcHJvZmlsZV9uYW1lGAMgASgJEg8KB25vZGVfaWQYBCABKAkiJQoRSXNzdWVMZWFmUmVzcG9uc2USEAoIY2VydF9kZXIYASABKAwiTAoQUmVrZXlOb2RlUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSFAoMcHJvZmlsZV9uYW1lGAIgASgJEg8KB25vZGVfaWQYAyABKAkiTQoRUmVrZXlOb2RlUmVzcG9uc2USEgoKc3ViamVjdF9jbhgBIAEoCRIRCglpc3N1ZXJfY24YAiABKAkSEQoJY2hhaW5fbGVuGAMgASgFIjoKFEdldE5vZGVDb25maWdSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJIkcKFUdldE5vZGVDb25maWdSZXNwb25zZRIuCgZjb25maWcYASABKAsyHi5jcnlwdG9zLm5vZGUudjEuTWFjaGluZUNvbmZpZyJsChZBcHBseU5vZGVDb25maWdSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIuCgZjb25maWcYAiABKAsyHi5jcnlwdG9zLm5vZGUudjEuTWFjaGluZUNvbmZpZxIPCgdub2RlX2lkGAMgASgJIkYKF0FwcGx5Tm9kZUNvbmZpZ1Jlc3BvbnNlEhIKCmdlbmVyYXRpb24YASABKAQSFwoPcmVxdWlyZXNfcmVib290GAIgASgIInAKFlNldE5vZGVQcm90b2NvbFJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEjIKCHByb3RvY29sGAIgASgOMiAuY3J5cHRvcy5ub2RlLnYxLlNlcnZpY2VQcm90b2NvbBIPCgdlbmFibGVkGAMgASgIIkYKF1NldE5vZGVQcm90b2NvbFJlc3BvbnNlEhIKCmdlbmVyYXRpb24YASABKAQSFwoPcmVxdWlyZXNfcmVib290GAIgASgIIkwKEkV4cG9ydENBS2V5UmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSEgoKcGFzc3BocmFzZRgCIAEoDBIPCgdub2RlX2lkGAMgASgJIicKE0V4cG9ydENBS2V5UmVzcG9uc2USEAoIZW52ZWxvcGUYASABKAwiXgoSSW1wb3J0Q0FLZXlSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIQCghlbnZlbG9wZRgCIAEoDBISCgpwYXNzcGhyYXNlGAMgASgMEg8KB25vZGVfaWQYBCABKAkiPAoTSW1wb3J0Q0FLZXlSZXNwb25zZRISCgpzdWJqZWN0X2NuGAEgASgJEhEKCWlzc3Vlcl9jbhgCIAEoCSJvCh9SZXZva2VPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0EhIKCnNlcmlhbF9oZXgYASABKAkSEwoLcmVhc29uX2NvZGUYAiABKAUSFQoNaXNzdWVyX3NoYTI1NhgDIAEoCRIMCgRub3RlGAQgASgJInMKIFJldm9rZU9wZXJhdG9yQ3JlZGVudGlhbFJlc3BvbnNlEhIKCnNlcmlhbF9oZXgYASABKAkSEgoKcmV2b2tlZF9hdBgCIAEoCRIVCg1pc3N1ZXJfc2hhMjU2GAMgASgJEhAKCHdhcm5pbmdzGAQgAygJIiAKHkxpc3RPcGVyYXRvckNyZWRlbnRpYWxzUmVxdWVzdCKNAgoST3BlcmF0b3JDcmVkZW50aWFsEhMKC2NvbW1vbl9uYW1lGAEgASgJEhIKCnNlcmlhbF9oZXgYAiABKAkSDQoFbGV2ZWwYAyABKAkSEQoJbm90X2FmdGVyGAQgASgJEg8KB3Jldm9rZWQYBSABKAgSDAoEa2luZBgGIAEoCRIVCg1pc3N1ZXJfc2hhMjU2GAcgASgJEg0KBWVtYWlsGAggASgJEhEKCWZ1bGxfbmFtZRgJIAEoCRISCgpkZW55bGlzdGVkGAogASgIEhMKC2NybF9yZXZva2VkGAsgASgIEhUKDWZpcnN0X3NlZW5fYXQYDCABKAkSFAoMbGFzdF9zZWVuX2F0GA0gASgJIlYKH0xpc3RPcGVyYXRvckNyZWRlbnRpYWxzUmVzcG9uc2USMwoFaXRlbXMYASADKAsyJC5jcnlwdG9zLmZsZWV0LnYxLk9wZXJhdG9yQ3JlZGVudGlhbCJqCiZDcmVhdGVPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0UmVxdWVzdBINCgVsZXZlbBgBIAEoCRINCgVlbWFpbBgCIAEoCRIRCglmdWxsX25hbWUYAyABKAkSDwoHY3NyX2RlchgEIAEoDCKUAQonQ3JlYXRlT3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdFJlc3BvbnNlEhIKCnJlcXVlc3RfaWQYASABKAkSDwoHY3NyX3BlbRgCIAEoCRIXCg9leHRmaWxlX3NlY3Rpb24YAyABKAkSFwoPb3BlbnNzbF9jb21tYW5kGAQgASgJEhIKCmV4cGlyZXNfYXQYBSABKAkiNgolTGlzdE9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3RzUmVxdWVzdBINCgVzdGF0ZRgBIAEoCSJkCiZMaXN0T3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdHNSZXNwb25zZRI6CgVpdGVtcxgBIAMoCzIrLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdCI8CiZDYW5jZWxPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0UmVxdWVzdBISCgpyZXF1ZXN0X2lkGAEgASgJImcKJ0NhbmNlbE9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3RSZXNwb25zZRI8CgdyZXF1ZXN0GAEgASgLMisuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0ItEBChlPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0EgoKAmlkGAEgASgJEg0KBWxldmVsGAIgASgJEg0KBWVtYWlsGAMgASgJEhEKCWZ1bGxfbmFtZRgEIAEoCRIPCgdjc3JfcGVtGAUgASgJEg0KBXN0YXRlGAYgASgJEhUKDWNyZWF0ZWRfYnlfY24YByABKAkSEgoKY3JlYXRlZF9hdBgIIAEoCRISCgpleHBpcmVzX2F0GAkgASgJEhgKEGNvbXBsZXRlZF9zZXJpYWwYCiABKAkiWgofUmVjb3JkT3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdBIQCghjZXJ0X2RlchgBIAEoDBISCgpyZXF1ZXN0X2lkGAIgASgJEhEKCWZ1bGxfbmFtZRgDIAEoCSJuCiBSZWNvcmRPcGVyYXRvckNyZWRlbnRpYWxSZXNwb25zZRI4CgpjcmVkZW50aWFsGAEgASgLMiQuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNyZWRlbnRpYWwSEAoId2FybmluZ3MYAiADKAkiGAoWTGlzdE9wZXJhdG9yQ0FzUmVxdWVzdCJGChdMaXN0T3BlcmF0b3JDQXNSZXNwb25zZRIrCgVpdGVtcxgBIAMoCzIcLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JDQSKQAgoZUmVnaXN0ZXJPcGVyYXRvckNBUmVxdWVzdBITCgtjYV9jZXJ0X2RlchgBIAEoDBINCgN1cmwYAiABKAlIABIRCgdjcmxfZGVyGAMgASgMSAASDgoEbm9uZRgEIAEoCEgAEi0KCW9jc3BfbW9kZRgFIAEoDjIaLmNyeXB0b3MuZmxlZXQudjEuT2NzcE1vZGUSEAoIb2NzcF91cmwYBiABKAkSRQoQYWNrbm93bGVkZ2VtZW50cxgHIAMoDjIrLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JDQUFja25vd2xlZGdlbWVudBIWCg5jb25maXJtX3NoYTI1NhgIIAEoCUIMCgpjcmxfc291cmNlIrABChpSZWdpc3Rlck9wZXJhdG9yQ0FSZXNwb25zZRIxCgtvcGVyYXRvcl9jYRgBIAEoCzIcLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JDQRIRCgljb25maXJtZWQYAiABKAgSFQoNYWRtaW5fZXh0ZmlsZRgDIAEoCRI1CgpvY3NwX3Byb2JlGAQgASgLMiEuY3J5cHRvcy5mbGVldC52MS5PY3NwUHJvYmVSZXN1bHQiTAoXUmV0aXJlT3BlcmF0b3JDQVJlcXVlc3QSDgoGc2hhMjU2GAEgASgJEiEKGWlfdW5kZXJzdGFuZF9zZWxmX2xvY2tvdXQYAiABKAgiTQoYUmV0aXJlT3BlcmF0b3JDQVJlc3BvbnNlEjEKC29wZXJhdG9yX2NhGAEgASgLMhwuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNBIrYBCh1TZXRPcGVyYXRvckNBQ1JMU291cmNlUmVxdWVzdBIOCgZzaGEyNTYYASABKAkSDQoDdXJsGAIgASgJSAASDgoEbm9uZRgDIAEoCEgAEhEKB2NybF9kZXIYBSABKAxIABJFChBhY2tub3dsZWRnZW1lbnRzGAQgAygOMisuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNBQWNrbm93bGVkZ2VtZW50QgwKCmNybF9zb3VyY2UiUwoeU2V0T3BlcmF0b3JDQUNSTFNvdXJjZVJlc3BvbnNlEjEKC29wZXJhdG9yX2NhGAEgASgLMhwuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNBIjsKGFVwbG9hZE9wZXJhdG9yQ1JMUmVxdWVzdBIOCgZzaGEyNTYYASABKAkSDwoHY3JsX2RlchgCIAEoDCJOChlVcGxvYWRPcGVyYXRvckNSTFJlc3BvbnNlEjEKC29wZXJhdG9yX2NhGAEgASgLMhwuY3J5cHRvcy5mbGVldC52MS5PcGVyYXRvckNBImsKGFNldE9wZXJhdG9yQ0FPQ1NQUmVxdWVzdBIOCgZzaGEyNTYYASABKAkSLQoJb2NzcF9tb2RlGAIgASgOMhouY3J5cHRvcy5mbGVldC52MS5PY3NwTW9kZRIQCghvY3NwX3VybBgDIAEoCSKFAQoZU2V0T3BlcmF0b3JDQU9DU1BSZXNwb25zZRIxCgtvcGVyYXRvcl9jYRgBIAEoCzIcLmNyeXB0b3MuZmxlZXQudjEuT3BlcmF0b3JDQRI1CgpvY3NwX3Byb2JlGAIgASgLMiEuY3J5cHRvcy5mbGVldC52MS5PY3NwUHJvYmVSZXN1bHQiKgoWUHJldmlld0Fkb3B0aW9uUmVxdWVzdBIQCghlbmRwb2ludBgBIAEoCSI/ChdQcmV2aWV3QWRvcHRpb25SZXNwb25zZRITCgtjZXJ0X3NoYTI1NhgBIAEoCRIPCgdzdWJqZWN0GAIgASgJIkcKF0xpc3RJbnN0YWxsRGlza3NSZXF1ZXN0EhAKCGVuZHBvaW50GAEgASgJEhoKEnBpbm5lZF9jZXJ0X3NoYTI1NhgCIAEoCSJHChhMaXN0SW5zdGFsbERpc2tzUmVzcG9uc2USKwoFZGlza3MYASADKAsyHC5jcnlwdG9zLm5vZGUudjEuSW5zdGFsbERpc2sicAoQQWRvcHROb2RlUmVxdWVzdBIQCghlbmRwb2ludBgBIAEoCRIaChJwaW5uZWRfY2VydF9zaGEyNTYYAiABKAkSLgoGY29uZmlnGAMgASgLMh4uY3J5cHRvcy5ub2RlLnYxLk1hY2hpbmVDb25maWcihQEKEUFkb3B0Tm9kZVJlc3BvbnNlEg0KBXBoYXNlGAEgASgJEg4KBmRldGFpbBgCIAEoCRIMCgRkb25lGAMgASgIEg8KB25vZGVfaWQYBCABKAkSEwoLYWRvcHRpb25faWQYBSABKAkSHQoVcHJlc2VudGVkX2NlcnRfc2hhMjU2GAYgASgJIk0KIUNvbmZpcm1BZG9wdGlvbkZpbmdlcnByaW50UmVxdWVzdBITCgthZG9wdGlvbl9pZBgBIAEoCRITCgtjZXJ0X3NoYTI1NhgCIAEoCSIkCiJDb25maXJtQWRvcHRpb25GaW5nZXJwcmludFJlc3BvbnNlIloKF0RlY29tbWlzc2lvbk5vZGVSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIbChNjb25maXJtX2NvbW1vbl9uYW1lGAIgASgJEg8KB25vZGVfaWQYAyABKAkiLQoYRGVjb21taXNzaW9uTm9kZVJlc3BvbnNlEhEKCXJlYm9vdGluZxgBIAEoCCJhChFSZWJvb3ROb2RlUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSFQoNY29uZmlybV9jYV9jbhgCIAEoCRIRCglwb3dlcl9vZmYYAyABKAgSDwoHbm9kZV9pZBgEIAEoCSInChJSZWJvb3ROb2RlUmVzcG9uc2USEQoJcmVib290aW5nGAEgASgIIjYKEVJlbmFtZU5vZGVSZXF1ZXN0Eg8KB25vZGVfaWQYASABKAkSEAoIbmV3X25hbWUYAiABKAkiQQoSUmVuYW1lTm9kZVJlc3BvbnNlEisKBG5vZGUYASABKAsyHS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVTdW1tYXJ5IjoKEVJlbW92ZU5vZGVSZXF1ZXN0Eg8KB25vZGVfaWQYASABKAkSFAoMY29uZmlybV9uYW1lGAIgASgJIkEKElJlbW92ZU5vZGVSZXNwb25zZRIrCgRub2RlGAEgASgLMh0uY3J5cHRvcy5mbGVldC52MS5Ob2RlU3VtbWFyeSIhChJMaXN0TWNwS2V5c1JlcXVlc3QSCwoDYWxsGAEgASgIIj4KE0xpc3RNY3BLZXlzUmVzcG9uc2USJwoFaXRlbXMYASADKAsyGC5jcnlwdG9zLmZsZWV0LnYxLk1jcEtleSIhChNSZXZva2VNY3BLZXlSZXF1ZXN0EgoKAmlkGAEgASgJIkEKFFJldm9rZU1jcEtleVJlc3BvbnNlEikKB21jcF9rZXkYASABKAsyGC5jcnlwdG9zLmZsZWV0LnYxLk1jcEtleSI7ChNDcmVhdGVNY3BLZXlSZXF1ZXN0Eg0KBWxhYmVsGAEgASgJEhUKDWxldmVsX2NlaWxpbmcYAiABKAkiWAoUQ3JlYXRlTWNwS2V5UmVzcG9uc2USFQoNcGxhaW50ZXh0X2tleRgBIAEoCRIpCgdtY3Bfa2V5GAIgASgLMhguY3J5cHRvcy5mbGVldC52MS5NY3BLZXkiuwEKBk1jcEtleRIKCgJpZBgBIAEoCRINCgVsYWJlbBgCIAEoCRITCgtjbGllbnRfbmFtZRgDIAEoCRITCgtvcGVyYXRvcl9jbhgEIAEoCRIXCg9vcGVyYXRvcl9zZXJpYWwYBSABKAkSFQoNbGV2ZWxfY2VpbGluZxgGIAEoCRISCgpjcmVhdGVkX2F0GAcgASgJEhQKDGxhc3RfdXNlZF9hdBgIIAEoCRISCgpyZXZva2VkX2F0GAkgASgJIiYKFExpc3RBcHByb3ZhbHNSZXF1ZXN0Eg4KBnN0YXR1cxgBIAEoCSJCChVMaXN0QXBwcm92YWxzUmVzcG9uc2USKQoFaXRlbXMYASADKAsyGi5jcnlwdG9zLmZsZWV0LnYxLkFwcHJvdmFsIjQKFURlY2lkZUFwcHJvdmFsUmVxdWVzdBIKCgJpZBgBIAEoCRIPCgdhcHByb3ZlGAIgASgIIkYKFkRlY2lkZUFwcHJvdmFsUmVzcG9uc2USLAoIYXBwcm92YWwYASABKAsyGi5jcnlwdG9zLmZsZWV0LnYxLkFwcHJvdmFsIrcCCghBcHByb3ZhbBIKCgJpZBgBIAEoCRIMCgR0b29sGAIgASgJEg8KB3N1bW1hcnkYAyABKAkSFgoOcmVxdWVzdF9kaWdlc3QYBCABKAkSFwoPcmVxdWVzdGVkX2J5X2NuGAUgASgJEhsKE3JlcXVlc3RlZF9ieV9zZXJpYWwYBiABKAkSDgoGa2V5X2lkGAcgASgJEhYKDnJlcXVpcmVkX2xldmVsGAggASgJEhIKCmNyZWF0ZWRfYXQYCSABKAkSEgoKZXhwaXJlc19hdBgKIAEoCRIOCgZzdGF0dXMYCyABKAkSFQoNZGVjaWRlZF9ieV9jbhgMIAEoCRIZChFkZWNpZGVkX2J5X3NlcmlhbBgNIAEoCRISCgpkZWNpZGVkX2F0GA4gASgJEgwKBGtpbmQYDyABKAkirwIKEkNlcnRpZmljYXRlUmVxdWVzdBIKCgJpZBgBIAEoCRIUCgxwcm9maWxlX25hbWUYAiABKAkSDwoHY3NyX3BlbRgDIAEoCRIMCgRub3RlGAQgASgJEhcKD3JlcXVlc3RlZF9ieV9jbhgFIAEoCRIbChNyZXF1ZXN0ZWRfYnlfc2VyaWFsGAYgASgJEg0KBXN0YXRlGAcgASgJEhMKC2FwcHJvdmFsX2lkGAggASgJEhcKD2NlcnRpZmljYXRlX3BlbRgJIAEoCRIWCg5mYWlsdXJlX3JlYXNvbhgKIAEoCRISCgpjcmVhdGVkX2F0GAsgASgJEhIKCmV4cGlyZXNfYXQYDCABKAkSEgoKZGVjaWRlZF9hdBgNIAEoCRIRCglpc3N1ZWRfYXQYDiABKAkiVgofQ3JlYXRlQ2VydGlmaWNhdGVSZXF1ZXN0UmVxdWVzdBIUCgxwcm9maWxlX25hbWUYASABKAkSDwoHY3NyX2RlchgCIAEoDBIMCgRub3RlGAMgASgJIlkKIENyZWF0ZUNlcnRpZmljYXRlUmVxdWVzdFJlc3BvbnNlEjUKB3JlcXVlc3QYASABKAsyJC5jcnlwdG9zLmZsZWV0LnYxLkNlcnRpZmljYXRlUmVxdWVzdCJCCh5MaXN0Q2VydGlmaWNhdGVSZXF1ZXN0c1JlcXVlc3QSDQoFc3RhdGUYASABKAkSEQoJbWluZV9vbmx5GAIgASgIIlYKH0xpc3RDZXJ0aWZpY2F0ZVJlcXVlc3RzUmVzcG9uc2USMwoFaXRlbXMYASADKAsyJC5jcnlwdG9zLmZsZWV0LnYxLkNlcnRpZmljYXRlUmVxdWVzdCIuCiBHZXRDZXJ0aWZpY2F0ZVJlcXVlc3RCeUlEUmVxdWVzdBIKCgJpZBgBIAEoCSJaCiFHZXRDZXJ0aWZpY2F0ZVJlcXVlc3RCeUlEUmVzcG9uc2USNQoHcmVxdWVzdBgBIAEoCzIkLmNyeXB0b3MuZmxlZXQudjEuQ2VydGlmaWNhdGVSZXF1ZXN0Ii0KH0NhbmNlbENlcnRpZmljYXRlUmVxdWVzdFJlcXVlc3QSCgoCaWQYASABKAkiWQogQ2FuY2VsQ2VydGlmaWNhdGVSZXF1ZXN0UmVzcG9uc2USNQoHcmVxdWVzdBgBIAEoCzIkLmNyeXB0b3MuZmxlZXQudjEuQ2VydGlmaWNhdGVSZXF1ZXN0IkQKHkxpc3ROb2RlVHNhQ2VydGlmaWNhdGVzUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSDwoHbm9kZV9pZBgCIAEoCSKGAQoSTm9kZVRzYUNlcnRpZmljYXRlEhAKCGNlcnRfcGVtGAEgASgJEhIKCnNlcmlhbF9oZXgYAiABKAkSEgoKc2hhMjU2X2hleBgDIAEoCRISCgpub3RfYmVmb3JlGAQgASgJEhEKCW5vdF9hZnRlchgFIAEoCRIPCgdjdXJyZW50GAYgASgIIl0KH0xpc3ROb2RlVHNhQ2VydGlmaWNhdGVzUmVzcG9uc2USOgoMY2VydGlmaWNhdGVzGAEgAygLMiQuY3J5cHRvcy5mbGVldC52MS5Ob2RlVHNhQ2VydGlmaWNhdGUiXgofVmFsaWRhdGVDZXJ0aWZpY2F0ZUNoYWluUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSDwoHbm9kZV9pZBgCIAEoCRIXCg9jZXJ0aWZpY2F0ZV9wZW0YAyABKAkiewogVmFsaWRhdGVDZXJ0aWZpY2F0ZUNoYWluUmVzcG9uc2USDQoFdmFsaWQYASABKAgSDgoGcmVhc29uGAIgASgJEg8KB3N1YmplY3QYAyABKAkSDgoGaXNzdWVyGAQgASgJEhcKD25vZGVfY2Ffc3ViamVjdBgFIAEoCSKuAQoaTGlzdE5vZGVBdWRpdEV2ZW50c1JlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEg8KB25vZGVfaWQYAiABKAkSEQoJcGFnZV9zaXplGAMgASgFEhIKCnBhZ2VfdG9rZW4YBCABKAkSEQoJZnJvbV90aW1lGAUgASgJEg8KB3RvX3RpbWUYBiABKAkSEgoKZXZlbnRfdHlwZRgHIAEoCRINCgVhY3RvchgIIAEoCSKQAgoOTm9kZUF1ZGl0RXZlbnQSCwoDc2VxGAEgASgEEgoKAnRzGAIgASgJEhUKDWFjdG9yX3N1YmplY3QYAyABKAkSEgoKcnBjX21ldGhvZBgEIAEoCRIPCgdvdXRjb21lGAUgASgJEj4KB2RldGFpbHMYBiADKAsyLS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVBdWRpdEV2ZW50LkRldGFpbHNFbnRyeRIYChBlbnRyeV9zaGEyNTZfaGV4GAcgASgJEg4KBnRhcmdldBgIIAEoCRIPCgdzdW1tYXJ5GAkgASgJGi4KDERldGFpbHNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBImkKG0xpc3ROb2RlQXVkaXRFdmVudHNSZXNwb25zZRIxCgdlbnRyaWVzGAEgAygLMiAuY3J5cHRvcy5mbGVldC52MS5Ob2RlQXVkaXRFdmVudBIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkiQQobVmVyaWZ5Tm9kZUF1ZGl0Q2hhaW5SZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJInIKHFZlcmlmeU5vZGVBdWRpdENoYWluUmVzcG9uc2USEwoLZW50cnlfY291bnQYASABKAQSDgoGaW50YWN0GAIgASgIEh0KFWZpcnN0X2Jyb2tlbl9zZXF1ZW5jZRgDIAEoBBIOCgZyZWFzb24YBCABKAkiPwoZR2V0Tm9kZUltYWdlU3RhdHVzUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSDwoHbm9kZV9pZBgCIAEoCSKKAQoPTm9kZUltYWdlU3RhdHVzEhYKDnJ1bm5pbmdfc2hhMjU2GAEgASgJEhUKDWFjdGl2ZV9zaGEyNTYYAiABKAkSFwoPcHJldmlvdXNfc2hhMjU2GAMgASgJEhYKDnJlYm9vdF9wZW5kaW5nGAQgASgIEhcKD3J1bm5pbmdfdmVyc2lvbhgFIAEoCSJPChpHZXROb2RlSW1hZ2VTdGF0dXNSZXNwb25zZRIxCgZzdGF0dXMYASABKAsyIS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVJbWFnZVN0YXR1cyJxChVTdGFnZU5vZGVJbWFnZVJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEg8KB25vZGVfaWQYAiABKAkSEQoJaW1hZ2VfdXJsGAMgASgJEhEKCXNpZ25hdHVyZRgEIAEoDBIOCgZzaGEyNTYYBSABKAkiZAoWU3RhZ2VOb2RlSW1hZ2VSZXNwb25zZRIxCgZzdGF0dXMYASABKAsyIS5jcnlwdG9zLmZsZWV0LnYxLk5vZGVJbWFnZVN0YXR1cxIXCg9yZXF1aXJlc19yZWJvb3QYAiABKAgiVQoYQWN0aXZhdGVOb2RlSW1hZ2VSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJEhUKDWNvbmZpcm1fY2FfY24YAyABKAkiLgoZQWN0aXZhdGVOb2RlSW1hZ2VSZXNwb25zZRIRCglyZWJvb3RpbmcYASABKAgiPgoYUm9sbGJhY2tOb2RlSW1hZ2VSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJImcKGVJvbGxiYWNrTm9kZUltYWdlUmVzcG9uc2USMQoGc3RhdHVzGAEgASgLMiEuY3J5cHRvcy5mbGVldC52MS5Ob2RlSW1hZ2VTdGF0dXMSFwoPcmVxdWlyZXNfcmVib290GAIgASgIIoQBChFOb2RlU2NlcENoYWxsZW5nZRIKCgJpZBgBIAEoCRIPCgdwcm9maWxlGAIgASgJEhMKC2JvdW5kX25hbWVzGAMgAygJEhIKCmNyZWF0ZWRfYXQYBCABKAkSEgoKZXhwaXJlc19hdBgFIAEoCRIVCg1jcmVhdGVkX2J5X2NuGAYgASgJIn0KHE1pbnROb2RlU2NlcENoYWxsZW5nZVJlcXVlc3QSEQoJbm9kZV9uYW1lGAEgASgJEg8KB25vZGVfaWQYAiABKAkSDwoHcHJvZmlsZRgDIAEoCRITCgt0dGxfc2Vjb25kcxgEIAEoDRITCgtib3VuZF9uYW1lcxgFIAMoCSJzCh1NaW50Tm9kZVNjZXBDaGFsbGVuZ2VSZXNwb25zZRIaChJjaGFsbGVuZ2VfcGFzc3dvcmQYASABKAkSNgoJY2hhbGxlbmdlGAIgASgLMiMuY3J5cHRvcy5mbGVldC52MS5Ob2RlU2NlcENoYWxsZW5nZSJDCh1MaXN0Tm9kZVNjZXBDaGFsbGVuZ2VzUmVxdWVzdBIRCglub2RlX25hbWUYASABKAkSDwoHbm9kZV9pZBgCIAEoCSJZCh5MaXN0Tm9kZVNjZXBDaGFsbGVuZ2VzUmVzcG9uc2USNwoKY2hhbGxlbmdlcxgBIAMoCzIjLmNyeXB0b3MuZmxlZXQudjEuTm9kZVNjZXBDaGFsbGVuZ2UiUAoeUmV2b2tlTm9kZVNjZXBDaGFsbGVuZ2VSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJEgoKAmlkGAMgASgJIlkKH1Jldm9rZU5vZGVTY2VwQ2hhbGxlbmdlUmVzcG9uc2USNgoJY2hhbGxlbmdlGAEgASgLMiMuY3J5cHRvcy5mbGVldC52MS5Ob2RlU2NlcENoYWxsZW5nZSLTAQoSTm9kZVNjZXBFbnJvbGxtZW50EgoKAmlkGAEgASgJEhYKDnRyYW5zYWN0aW9uX2lkGAIgASgJEg8KB3Byb2ZpbGUYAyABKAkSEgoKc3ViamVjdF9kbhgEIAEoCRIRCglkbnNfbmFtZXMYBSADKAkSFAoMaXBfYWRkcmVzc2VzGAYgAygJEg8KB2tleV9hbGcYByABKAkSDwoHY3NyX3BlbRgIIAEoCRIUCgxjaGFsbGVuZ2VfaWQYCSABKAkSEwoLcmVjZWl2ZWRfYXQYCiABKAkiVQoeTGlzdE5vZGVTY2VwRW5yb2xsbWVudHNSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJEg8KB3Byb2ZpbGUYAyABKAkiXAofTGlzdE5vZGVTY2VwRW5yb2xsbWVudHNSZXNwb25zZRI5CgtlbnJvbGxtZW50cxgBIAMoCzIkLmNyeXB0b3MuZmxlZXQudjEuTm9kZVNjZXBFbnJvbGxtZW50IlIKIEFwcHJvdmVOb2RlU2NlcEVucm9sbG1lbnRSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJEgoKAmlkGAMgASgJInEKIUFwcHJvdmVOb2RlU2NlcEVucm9sbG1lbnRSZXNwb25zZRI4CgplbnJvbGxtZW50GAEgASgLMiQuY3J5cHRvcy5mbGVldC52MS5Ob2RlU2NlcEVucm9sbG1lbnQSEgoKc2VyaWFsX2hleBgCIAEoCSJhCh9SZWplY3ROb2RlU2NlcEVucm9sbG1lbnRSZXF1ZXN0EhEKCW5vZGVfbmFtZRgBIAEoCRIPCgdub2RlX2lkGAIgASgJEgoKAmlkGAMgASgJEg4KBnJlYXNvbhgEIAEoCSJcCiBSZWplY3ROb2RlU2NlcEVucm9sbG1lbnRSZXNwb25zZRI4CgplbnJvbGxtZW50GAEgASgLMiQuY3J5cHRvcy5mbGVldC52MS5Ob2RlU2NlcEVucm9sbG1lbnQqUgoGSGVhbHRoEhYKEkhFQUxUSF9VTlNQRUNJRklFRBAAEg0KCUhFQUxUSF9VUBABEg8KC0hFQUxUSF9ET1dOEAISEAoMSEVBTFRIX0VSUk9SEAMyvzwKDEZsZWV0U2VydmljZRJUCglMaXN0Tm9kZXMSIi5jcnlwdG9zLmZsZWV0LnYxLkxpc3ROb2Rlc1JlcXVlc3QaIy5jcnlwdG9zLmZsZWV0LnYxLkxpc3ROb2Rlc1Jlc3BvbnNlEk4KB0dldE5vZGUSIC5jcnlwdG9zLmZsZWV0LnYxLkdldE5vZGVSZXF1ZXN0GiEuY3J5cHRvcy5mbGVldC52MS5HZXROb2RlUmVzcG9uc2USaQoQTGlzdENlcnRpZmljYXRlcxIpLmNyeXB0b3MuZmxlZXQudjEuTGlzdENlcnRpZmljYXRlc1JlcXVlc3QaKi5jcnlwdG9zLmZsZWV0LnYxLkxpc3RDZXJ0aWZpY2F0ZXNSZXNwb25zZRJdCgxMaXN0UHJvZmlsZXMSJS5jcnlwdG9zLmZsZWV0LnYxLkxpc3RQcm9maWxlc1JlcXVlc3QaJi5jcnlwdG9zLmZsZWV0LnYxLkxpc3RQcm9maWxlc1Jlc3BvbnNlEmAKDUNyZWF0ZVByb2ZpbGUSJi5jcnlwdG9zLmZsZWV0LnYxLkNyZWF0ZVByb2ZpbGVSZXF1ZXN0GicuY3J5cHRvcy5mbGVldC52MS5DcmVhdGVQcm9maWxlUmVzcG9uc2USYAoNVXBkYXRlUHJvZmlsZRImLmNyeXB0b3MuZmxlZXQudjEuVXBkYXRlUHJvZmlsZVJlcXVlc3QaJy5jcnlwdG9zLmZsZWV0LnYxLlVwZGF0ZVByb2ZpbGVSZXNwb25zZRJgCg1EZWxldGVQcm9maWxlEiYuY3J5cHRvcy5mbGVldC52MS5EZWxldGVQcm9maWxlUmVxdWVzdBonLmNyeXB0b3MuZmxlZXQudjEuRGVsZXRlUHJvZmlsZVJlc3BvbnNlEm8KEkFwcGx5UHJvZmlsZVRvTm9kZRIrLmNyeXB0b3MuZmxlZXQudjEuQXBwbHlQcm9maWxlVG9Ob2RlUmVxdWVzdBosLmNyeXB0b3MuZmxlZXQudjEuQXBwbHlQcm9maWxlVG9Ob2RlUmVzcG9uc2USeAoVU2V0UHJvZmlsZVJlcXVlc3RhYmxlEi4uY3J5cHRvcy5mbGVldC52MS5TZXRQcm9maWxlUmVxdWVzdGFibGVSZXF1ZXN0Gi8uY3J5cHRvcy5mbGVldC52MS5TZXRQcm9maWxlUmVxdWVzdGFibGVSZXNwb25zZRJ+ChdMaXN0UmVxdWVzdGFibGVQcm9maWxlcxIwLmNyeXB0b3MuZmxlZXQudjEuTGlzdFJlcXVlc3RhYmxlUHJvZmlsZXNSZXF1ZXN0GjEuY3J5cHRvcy5mbGVldC52MS5MaXN0UmVxdWVzdGFibGVQcm9maWxlc1Jlc3BvbnNlEl0KDExpc3RBZGFwdGVycxIlLmNyeXB0b3MuZmxlZXQudjEuTGlzdEFkYXB0ZXJzUmVxdWVzdBomLmNyeXB0b3MuZmxlZXQudjEuTGlzdEFkYXB0ZXJzUmVzcG9uc2USbAoRU2V0QWRhcHRlckVuYWJsZWQSKi5jcnlwdG9zLmZsZWV0LnYxLlNldEFkYXB0ZXJFbmFibGVkUmVxdWVzdBorLmNyeXB0b3MuZmxlZXQudjEuU2V0QWRhcHRlckVuYWJsZWRSZXNwb25zZRJmCg9TZXROb2RlUHJvdG9jb2wSKC5jcnlwdG9zLmZsZWV0LnYxLlNldE5vZGVQcm90b2NvbFJlcXVlc3QaKS5jcnlwdG9zLmZsZWV0LnYxLlNldE5vZGVQcm90b2NvbFJlc3BvbnNlElQKCUxpc3RBdWRpdBIiLmNyeXB0b3MuZmxlZXQudjEuTGlzdEF1ZGl0UmVxdWVzdBojLmNyeXB0b3MuZmxlZXQudjEuTGlzdEF1ZGl0UmVzcG9uc2USZgoPTGlzdEVucm9sbG1lbnRzEiguY3J5cHRvcy5mbGVldC52MS5MaXN0RW5yb2xsbWVudHNSZXF1ZXN0GikuY3J5cHRvcy5mbGVldC52MS5MaXN0RW5yb2xsbWVudHNSZXNwb25zZRJpChBDcmVhdGVFbnJvbGxtZW50EikuY3J5cHRvcy5mbGVldC52MS5DcmVhdGVFbnJvbGxtZW50UmVxdWVzdBoqLmNyeXB0b3MuZmxlZXQudjEuQ3JlYXRlRW5yb2xsbWVudFJlc3BvbnNlEmwKEUFwcHJvdmVFbnJvbGxtZW50EiouY3J5cHRvcy5mbGVldC52MS5BcHByb3ZlRW5yb2xsbWVudFJlcXVlc3QaKy5jcnlwdG9zLmZsZWV0LnYxLkFwcHJvdmVFbnJvbGxtZW50UmVzcG9uc2USaQoQUmVqZWN0RW5yb2xsbWVudBIpLmNyeXB0b3MuZmxlZXQudjEuUmVqZWN0RW5yb2xsbWVudFJlcXVlc3QaKi5jcnlwdG9zLmZsZWV0LnYxLlJlamVjdEVucm9sbG1lbnRSZXNwb25zZRJLCgZXaG9BbUkSHy5jcnlwdG9zLmZsZWV0LnYxLldob0FtSVJlcXVlc3QaIC5jcnlwdG9zLmZsZWV0LnYxLldob0FtSVJlc3BvbnNlEmwKEVJldm9rZUNlcnRpZmljYXRlEiouY3J5cHRvcy5mbGVldC52MS5SZXZva2VDZXJ0aWZpY2F0ZVJlcXVlc3QaKy5jcnlwdG9zLmZsZWV0LnYxLlJldm9rZUNlcnRpZmljYXRlUmVzcG9uc2USYwoOR2V0Q2VydGlmaWNhdGUSJy5jcnlwdG9zLmZsZWV0LnYxLkdldENlcnRpZmljYXRlUmVxdWVzdBooLmNyeXB0b3MuZmxlZXQudjEuR2V0Q2VydGlmaWNhdGVSZXNwb25zZRJyChNMaXN0Tm9kZUF1ZGl0RXZlbnRzEiwuY3J5cHRvcy5mbGVldC52MS5MaXN0Tm9kZUF1ZGl0RXZlbnRzUmVxdWVzdBotLmNyeXB0b3MuZmxlZXQudjEuTGlzdE5vZGVBdWRpdEV2ZW50c1Jlc3BvbnNlEnUKFFZlcmlmeU5vZGVBdWRpdENoYWluEi0uY3J5cHRvcy5mbGVldC52MS5WZXJpZnlOb2RlQXVkaXRDaGFpblJlcXVlc3QaLi5jcnlwdG9zLmZsZWV0LnYxLlZlcmlmeU5vZGVBdWRpdENoYWluUmVzcG9uc2USgQEKGFZhbGlkYXRlQ2VydGlmaWNhdGVDaGFpbhIxLmNyeXB0b3MuZmxlZXQudjEuVmFsaWRhdGVDZXJ0aWZpY2F0ZUNoYWluUmVxdWVzdBoyLmNyeXB0b3MuZmxlZXQudjEuVmFsaWRhdGVDZXJ0aWZpY2F0ZUNoYWluUmVzcG9uc2USfgoXTGlzdE5vZGVUc2FDZXJ0aWZpY2F0ZXMSMC5jcnlwdG9zLmZsZWV0LnYxLkxpc3ROb2RlVHNhQ2VydGlmaWNhdGVzUmVxdWVzdBoxLmNyeXB0b3MuZmxlZXQudjEuTGlzdE5vZGVUc2FDZXJ0aWZpY2F0ZXNSZXNwb25zZRJvChJHZXROb2RlSW1hZ2VTdGF0dXMSKy5jcnlwdG9zLmZsZWV0LnYxLkdldE5vZGVJbWFnZVN0YXR1c1JlcXVlc3QaLC5jcnlwdG9zLmZsZWV0LnYxLkdldE5vZGVJbWFnZVN0YXR1c1Jlc3BvbnNlEmMKDlN0YWdlTm9kZUltYWdlEicuY3J5cHRvcy5mbGVldC52MS5TdGFnZU5vZGVJbWFnZVJlcXVlc3QaKC5jcnlwdG9zLmZsZWV0LnYxLlN0YWdlTm9kZUltYWdlUmVzcG9uc2USbAoRQWN0aXZhdGVOb2RlSW1hZ2USKi5jcnlwdG9zLmZsZWV0LnYxLkFjdGl2YXRlTm9kZUltYWdlUmVxdWVzdBorLmNyeXB0b3MuZmxlZXQudjEuQWN0aXZhdGVOb2RlSW1hZ2VSZXNwb25zZRJsChFSb2xsYmFja05vZGVJbWFnZRIqLmNyeXB0b3MuZmxlZXQudjEuUm9sbGJhY2tOb2RlSW1hZ2VSZXF1ZXN0GisuY3J5cHRvcy5mbGVldC52MS5Sb2xsYmFja05vZGVJbWFnZVJlc3BvbnNlElQKCUlzc3VlTGVhZhIiLmNyeXB0b3MuZmxlZXQudjEuSXNzdWVMZWFmUmVxdWVzdBojLmNyeXB0b3MuZmxlZXQudjEuSXNzdWVMZWFmUmVzcG9uc2USVAoJUmVrZXlOb2RlEiIuY3J5cHRvcy5mbGVldC52MS5SZWtleU5vZGVSZXF1ZXN0GiMuY3J5cHRvcy5mbGVldC52MS5SZWtleU5vZGVSZXNwb25zZRJgCg1HZXROb2RlQ29uZmlnEiYuY3J5cHRvcy5mbGVldC52MS5HZXROb2RlQ29uZmlnUmVxdWVzdBonLmNyeXB0b3MuZmxlZXQudjEuR2V0Tm9kZUNvbmZpZ1Jlc3BvbnNlEmYKD0FwcGx5Tm9kZUNvbmZpZxIoLmNyeXB0b3MuZmxlZXQudjEuQXBwbHlOb2RlQ29uZmlnUmVxdWVzdBopLmNyeXB0b3MuZmxlZXQudjEuQXBwbHlOb2RlQ29uZmlnUmVzcG9uc2USWgoLRXhwb3J0Q0FLZXkSJC5jcnlwdG9zLmZsZWV0LnYxLkV4cG9ydENBS2V5UmVxdWVzdBolLmNyeXB0b3MuZmxlZXQudjEuRXhwb3J0Q0FLZXlSZXNwb25zZRJaCgtJbXBvcnRDQUtleRIkLmNyeXB0b3MuZmxlZXQudjEuSW1wb3J0Q0FLZXlSZXF1ZXN0GiUuY3J5cHRvcy5mbGVldC52MS5JbXBvcnRDQUtleVJlc3BvbnNlEpYBCh9DcmVhdGVPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0EjguY3J5cHRvcy5mbGVldC52MS5DcmVhdGVPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0UmVxdWVzdBo5LmNyeXB0b3MuZmxlZXQudjEuQ3JlYXRlT3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdFJlc3BvbnNlEpMBCh5MaXN0T3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdHMSNy5jcnlwdG9zLmZsZWV0LnYxLkxpc3RPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0c1JlcXVlc3QaOC5jcnlwdG9zLmZsZWV0LnYxLkxpc3RPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0c1Jlc3BvbnNlEpYBCh9DYW5jZWxPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0EjguY3J5cHRvcy5mbGVldC52MS5DYW5jZWxPcGVyYXRvckNyZWRlbnRpYWxSZXF1ZXN0UmVxdWVzdBo5LmNyeXB0b3MuZmxlZXQudjEuQ2FuY2VsT3BlcmF0b3JDcmVkZW50aWFsUmVxdWVzdFJlc3BvbnNlEoEBChhSZWNvcmRPcGVyYXRvckNyZWRlbnRpYWwSMS5jcnlwdG9zLmZsZWV0LnYxLlJlY29yZE9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3QaMi5jcnlwdG9zLmZsZWV0LnYxLlJlY29yZE9wZXJhdG9yQ3JlZGVudGlhbFJlc3BvbnNlEoEBChhSZXZva2VPcGVyYXRvckNyZWRlbnRpYWwSMS5jcnlwdG9zLmZsZWV0LnYxLlJldm9rZU9wZXJhdG9yQ3JlZGVudGlhbFJlcXVlc3QaMi5jcnlwdG9zLmZsZWV0LnYxLlJldm9rZU9wZXJhdG9yQ3JlZGVudGlhbFJlc3BvbnNlEn4KF0xpc3RPcGVyYXRvckNyZWRlbnRpYWxzEjAuY3J5cHRvcy5mbGVldC52MS5MaXN0T3BlcmF0b3JDcmVkZW50aWFsc1JlcXVlc3QaMS5jcnlwdG9zLmZsZWV0LnYxLkxpc3RPcGVyYXRvckNyZWRlbnRpYWxzUmVzcG9uc2USZgoPTGlzdE9wZXJhdG9yQ0FzEiguY3J5cHRvcy5mbGVldC52MS5MaXN0T3BlcmF0b3JDQXNSZXF1ZXN0GikuY3J5cHRvcy5mbGVldC52MS5MaXN0T3BlcmF0b3JDQXNSZXNwb25zZRJvChJSZWdpc3Rlck9wZXJhdG9yQ0ESKy5jcnlwdG9zLmZsZWV0LnYxLlJlZ2lzdGVyT3BlcmF0b3JDQVJlcXVlc3QaLC5jcnlwdG9zLmZsZWV0LnYxLlJlZ2lzdGVyT3BlcmF0b3JDQVJlc3BvbnNlEmkKEFJldGlyZU9wZXJhdG9yQ0ESKS5jcnlwdG9zLmZsZWV0LnYxLlJldGlyZU9wZXJhdG9yQ0FSZXF1ZXN0GiouY3J5cHRvcy5mbGVldC52MS5SZXRpcmVPcGVyYXRvckNBUmVzcG9uc2USewoWU2V0T3BlcmF0b3JDQUNSTFNvdXJjZRIvLmNyeXB0b3MuZmxlZXQudjEuU2V0T3BlcmF0b3JDQUNSTFNvdXJjZVJlcXVlc3QaMC5jcnlwdG9zLmZsZWV0LnYxLlNldE9wZXJhdG9yQ0FDUkxTb3VyY2VSZXNwb25zZRJsChFVcGxvYWRPcGVyYXRvckNSTBIqLmNyeXB0b3MuZmxlZXQudjEuVXBsb2FkT3BlcmF0b3JDUkxSZXF1ZXN0GisuY3J5cHRvcy5mbGVldC52MS5VcGxvYWRPcGVyYXRvckNSTFJlc3BvbnNlEmwKEVNldE9wZXJhdG9yQ0FPQ1NQEiouY3J5cHRvcy5mbGVldC52MS5TZXRPcGVyYXRvckNBT0NTUFJlcXVlc3QaKy5jcnlwdG9zLmZsZWV0LnYxLlNldE9wZXJhdG9yQ0FPQ1NQUmVzcG9uc2USZgoPUHJldmlld0Fkb3B0aW9uEiguY3J5cHRvcy5mbGVldC52MS5QcmV2aWV3QWRvcHRpb25SZXF1ZXN0GikuY3J5cHRvcy5mbGVldC52MS5QcmV2aWV3QWRvcHRpb25SZXNwb25zZRJpChBMaXN0SW5zdGFsbERpc2tzEikuY3J5cHRvcy5mbGVldC52MS5MaXN0SW5zdGFsbERpc2tzUmVxdWVzdBoqLmNyeXB0b3MuZmxlZXQudjEuTGlzdEluc3RhbGxEaXNrc1Jlc3BvbnNlElYKCUFkb3B0Tm9kZRIiLmNyeXB0b3MuZmxlZXQudjEuQWRvcHROb2RlUmVxdWVzdBojLmNyeXB0b3MuZmxlZXQudjEuQWRvcHROb2RlUmVzcG9uc2UwARKHAQoaQ29uZmlybUFkb3B0aW9uRmluZ2VycHJpbnQSMy5jcnlwdG9zLmZsZWV0LnYxLkNvbmZpcm1BZG9wdGlvbkZpbmdlcnByaW50UmVxdWVzdBo0LmNyeXB0b3MuZmxlZXQudjEuQ29uZmlybUFkb3B0aW9uRmluZ2VycHJpbnRSZXNwb25zZRJpChBEZWNvbW1pc3Npb25Ob2RlEikuY3J5cHRvcy5mbGVldC52MS5EZWNvbW1pc3Npb25Ob2RlUmVxdWVzdBoqLmNyeXB0b3MuZmxlZXQudjEuRGVjb21taXNzaW9uTm9kZVJlc3BvbnNlElcKClJlYm9vdE5vZGUSIy5jcnlwdG9zLmZsZWV0LnYxLlJlYm9vdE5vZGVSZXF1ZXN0GiQuY3J5cHRvcy5mbGVldC52MS5SZWJvb3ROb2RlUmVzcG9uc2USVwoKUmVuYW1lTm9kZRIjLmNyeXB0b3MuZmxlZXQudjEuUmVuYW1lTm9kZVJlcXVlc3QaJC5jcnlwdG9zLmZsZWV0LnYxLlJlbmFtZU5vZGVSZXNwb25zZRJXCgpSZW1vdmVOb2RlEiMuY3J5cHRvcy5mbGVldC52MS5SZW1vdmVOb2RlUmVxdWVzdBokLmNyeXB0b3MuZmxlZXQudjEuUmVtb3ZlTm9kZVJlc3BvbnNlEloKC0xpc3RNY3BLZXlzEiQuY3J5cHRvcy5mbGVldC52MS5MaXN0TWNwS2V5c1JlcXVlc3QaJS5jcnlwdG9zLmZsZWV0LnYxLkxpc3RNY3BLZXlzUmVzcG9uc2USXQoMUmV2b2tlTWNwS2V5EiUuY3J5cHRvcy5mbGVldC52MS5SZXZva2VNY3BLZXlSZXF1ZXN0GiYuY3J5cHRvcy5mbGVldC52MS5SZXZva2VNY3BLZXlSZXNwb25zZRJdCgxDcmVhdGVNY3BLZXkSJS5jcnlwdG9zLmZsZWV0LnYxLkNyZWF0ZU1jcEtleVJlcXVlc3QaJi5jcnlwdG9zLmZsZWV0LnYxLkNyZWF0ZU1jcEtleVJlc3BvbnNlEmAKDUxpc3RBcHByb3ZhbHMSJi5jcnlwdG9zLmZsZWV0LnYxLkxpc3RBcHByb3ZhbHNSZXF1ZXN0GicuY3J5cHRvcy5mbGVldC52MS5MaXN0QXBwcm92YWxzUmVzcG9uc2USYwoORGVjaWRlQXBwcm92YWwSJy5jcnlwdG9zLmZsZWV0LnYxLkRlY2lkZUFwcHJvdmFsUmVxdWVzdBooLmNyeXB0b3MuZmxlZXQudjEuRGVjaWRlQXBwcm92YWxSZXNwb25zZRKBAQoYQ3JlYXRlQ2VydGlmaWNhdGVSZXF1ZXN0EjEuY3J5cHRvcy5mbGVldC52MS5DcmVhdGVDZXJ0aWZpY2F0ZVJlcXVlc3RSZXF1ZXN0GjIuY3J5cHRvcy5mbGVldC52MS5DcmVhdGVDZXJ0aWZpY2F0ZVJlcXVlc3RSZXNwb25zZRJ+ChdMaXN0Q2VydGlmaWNhdGVSZXF1ZXN0cxIwLmNyeXB0b3MuZmxlZXQudjEuTGlzdENlcnRpZmljYXRlUmVxdWVzdHNSZXF1ZXN0GjEuY3J5cHRvcy5mbGVldC52MS5MaXN0Q2VydGlmaWNhdGVSZXF1ZXN0c1Jlc3BvbnNlEoQBChlHZXRDZXJ0aWZpY2F0ZVJlcXVlc3RCeUlEEjIuY3J5cHRvcy5mbGVldC52MS5HZXRDZXJ0aWZpY2F0ZVJlcXVlc3RCeUlEUmVxdWVzdBozLmNyeXB0b3MuZmxlZXQudjEuR2V0Q2VydGlmaWNhdGVSZXF1ZXN0QnlJRFJlc3BvbnNlEoEBChhDYW5jZWxDZXJ0aWZpY2F0ZVJlcXVlc3QSMS5jcnlwdG9zLmZsZWV0LnYxLkNhbmNlbENlcnRpZmljYXRlUmVxdWVzdFJlcXVlc3QaMi5jcnlwdG9zLmZsZWV0LnYxLkNhbmNlbENlcnRpZmljYXRlUmVxdWVzdFJlc3BvbnNlEngKFU1pbnROb2RlU2NlcENoYWxsZW5nZRIuLmNyeXB0b3MuZmxlZXQudjEuTWludE5vZGVTY2VwQ2hhbGxlbmdlUmVxdWVzdBovLmNyeXB0b3MuZmxlZXQudjEuTWludE5vZGVTY2VwQ2hhbGxlbmdlUmVzcG9uc2USewoWTGlzdE5vZGVTY2VwQ2hhbGxlbmdlcxIvLmNyeXB0b3MuZmxlZXQudjEuTGlzdE5vZGVTY2VwQ2hhbGxlbmdlc1JlcXVlc3QaMC5jcnlwdG9zLmZsZWV0LnYxLkxpc3ROb2RlU2NlcENoYWxsZW5nZXNSZXNwb25zZRJ+ChdSZXZva2VOb2RlU2NlcENoYWxsZW5nZRIwLmNyeXB0b3MuZmxlZXQudjEuUmV2b2tlTm9kZVNjZXBDaGFsbGVuZ2VSZXF1ZXN0GjEuY3J5cHRvcy5mbGVldC52MS5SZXZva2VOb2RlU2NlcENoYWxsZW5nZVJlc3BvbnNlEn4KF0xpc3ROb2RlU2NlcEVucm9sbG1lbnRzEjAuY3J5cHRvcy5mbGVldC52MS5MaXN0Tm9kZVNjZXBFbnJvbGxtZW50c1JlcXVlc3QaMS5jcnlwdG9zLmZsZWV0LnYxLkxpc3ROb2RlU2NlcEVucm9sbG1lbnRzUmVzcG9uc2UShAEKGUFwcHJvdmVOb2RlU2NlcEVucm9sbG1lbnQSMi5jcnlwdG9zLmZsZWV0LnYxLkFwcHJvdmVOb2RlU2NlcEVucm9sbG1lbnRSZXF1ZXN0GjMuY3J5cHRvcy5mbGVldC52MS5BcHByb3ZlTm9kZVNjZXBFbnJvbGxtZW50UmVzcG9uc2USgQEKGFJlamVjdE5vZGVTY2VwRW5yb2xsbWVudBIxLmNyeXB0b3MuZmxlZXQudjEuUmVqZWN0Tm9kZVNjZXBFbnJvbGxtZW50UmVxdWVzdBoyLmNyeXB0b3MuZmxlZXQudjEuUmVqZWN0Tm9kZVNjZXBFbnJvbGxtZW50UmVzcG9uc2VCSFpGZ2l0aHViLmNvbS9DcnlwdE9TLVBLSS9jcnlwdG9zLW1hbmFnZXIvZ2VuL2dvL2NyeXB0b3MvZmxlZXQvdjE7ZmxlZXR2MWIGcHJvdG8z", [file_cryptos_fleet_v1_operator_ca, file_cryptos_node_v1_config, file_cryptos_node_v1_node, file_cryptos_node_v1_status]); /** * @generated from message cryptos.fleet.v1.ListNodesRequest @@ -4898,6 +4898,243 @@ export type RevokeNodeScepChallengeResponse = Message<"cryptos.fleet.v1.RevokeNo export const RevokeNodeScepChallengeResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_cryptos_fleet_v1_fleet, 150); +/** + * NodeScepEnrollment is an initial SCEP enrolment on a managed node, held for + * an operator decision. The challenge that authorized it was consumed on + * arrival and is not carried. + * + * @generated from message cryptos.fleet.v1.NodeScepEnrollment + */ +export type NodeScepEnrollment = Message<"cryptos.fleet.v1.NodeScepEnrollment"> & { + /** + * id identifies the enrolment for approval or rejection. + * + * @generated from field: string id = 1; + */ + id: string; + + /** + * transaction_id is the client's SCEP transactionID (RFC 8894 section + * 3.2.1.1). + * + * @generated from field: string transaction_id = 2; + */ + transactionId: string; + + /** + * profile is the node's Scep.profiles entry it will issue from. + * + * @generated from field: string profile = 3; + */ + profile: string; + + /** + * subject_dn is the subject the request asks for, as an RFC 4514 string. + * + * @generated from field: string subject_dn = 4; + */ + subjectDn: string; + + /** + * @generated from field: repeated string dns_names = 5; + */ + dnsNames: string[]; + + /** + * @generated from field: repeated string ip_addresses = 6; + */ + ipAddresses: string[]; + + /** + * key_alg is the requested subject key, for example "RSA-2048" or + * "ECDSA-P384". + * + * @generated from field: string key_alg = 7; + */ + keyAlg: string; + + /** + * csr_pem is the PKCS#10 request the client signed, PEM-encoded, for an + * operator who wants to inspect it before deciding. + * + * @generated from field: string csr_pem = 8; + */ + csrPem: string; + + /** + * challenge_id is the id of the challenge that authorized the request. + * + * @generated from field: string challenge_id = 9; + */ + challengeId: string; + + /** + * @generated from field: string received_at = 10; + */ + receivedAt: string; +}; + +/** + * Describes the message cryptos.fleet.v1.NodeScepEnrollment. + * Use `create(NodeScepEnrollmentSchema)` to create a new message. + */ +export const NodeScepEnrollmentSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_cryptos_fleet_v1_fleet, 151); + +/** + * @generated from message cryptos.fleet.v1.ListNodeScepEnrollmentsRequest + */ +export type ListNodeScepEnrollmentsRequest = Message<"cryptos.fleet.v1.ListNodeScepEnrollmentsRequest"> & { + /** + * @generated from field: string node_name = 1; + */ + nodeName: string; + + /** + * @generated from field: string node_id = 2; + */ + nodeId: string; + + /** + * profile, when set, keeps only enrolments for that profile. + * + * @generated from field: string profile = 3; + */ + profile: string; +}; + +/** + * Describes the message cryptos.fleet.v1.ListNodeScepEnrollmentsRequest. + * Use `create(ListNodeScepEnrollmentsRequestSchema)` to create a new message. + */ +export const ListNodeScepEnrollmentsRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_cryptos_fleet_v1_fleet, 152); + +/** + * @generated from message cryptos.fleet.v1.ListNodeScepEnrollmentsResponse + */ +export type ListNodeScepEnrollmentsResponse = Message<"cryptos.fleet.v1.ListNodeScepEnrollmentsResponse"> & { + /** + * @generated from field: repeated cryptos.fleet.v1.NodeScepEnrollment enrollments = 1; + */ + enrollments: NodeScepEnrollment[]; +}; + +/** + * Describes the message cryptos.fleet.v1.ListNodeScepEnrollmentsResponse. + * Use `create(ListNodeScepEnrollmentsResponseSchema)` to create a new message. + */ +export const ListNodeScepEnrollmentsResponseSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_cryptos_fleet_v1_fleet, 153); + +/** + * @generated from message cryptos.fleet.v1.ApproveNodeScepEnrollmentRequest + */ +export type ApproveNodeScepEnrollmentRequest = Message<"cryptos.fleet.v1.ApproveNodeScepEnrollmentRequest"> & { + /** + * @generated from field: string node_name = 1; + */ + nodeName: string; + + /** + * @generated from field: string node_id = 2; + */ + nodeId: string; + + /** + * @generated from field: string id = 3; + */ + id: string; +}; + +/** + * Describes the message cryptos.fleet.v1.ApproveNodeScepEnrollmentRequest. + * Use `create(ApproveNodeScepEnrollmentRequestSchema)` to create a new message. + */ +export const ApproveNodeScepEnrollmentRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_cryptos_fleet_v1_fleet, 154); + +/** + * @generated from message cryptos.fleet.v1.ApproveNodeScepEnrollmentResponse + */ +export type ApproveNodeScepEnrollmentResponse = Message<"cryptos.fleet.v1.ApproveNodeScepEnrollmentResponse"> & { + /** + * enrollment is the approved enrolment, now out of the queue. + * + * @generated from field: cryptos.fleet.v1.NodeScepEnrollment enrollment = 1; + */ + enrollment?: NodeScepEnrollment | undefined; + + /** + * serial_hex is the serial of the issued certificate, which + * ListCertificates and RevokeCertificate know it by. + * + * @generated from field: string serial_hex = 2; + */ + serialHex: string; +}; + +/** + * Describes the message cryptos.fleet.v1.ApproveNodeScepEnrollmentResponse. + * Use `create(ApproveNodeScepEnrollmentResponseSchema)` to create a new message. + */ +export const ApproveNodeScepEnrollmentResponseSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_cryptos_fleet_v1_fleet, 155); + +/** + * @generated from message cryptos.fleet.v1.RejectNodeScepEnrollmentRequest + */ +export type RejectNodeScepEnrollmentRequest = Message<"cryptos.fleet.v1.RejectNodeScepEnrollmentRequest"> & { + /** + * @generated from field: string node_name = 1; + */ + nodeName: string; + + /** + * @generated from field: string node_id = 2; + */ + nodeId: string; + + /** + * @generated from field: string id = 3; + */ + id: string; + + /** + * reason is recorded in the node's own audit log. It is not sent to the + * device, which RFC 8894 answers only with a failInfo code. + * + * @generated from field: string reason = 4; + */ + reason: string; +}; + +/** + * Describes the message cryptos.fleet.v1.RejectNodeScepEnrollmentRequest. + * Use `create(RejectNodeScepEnrollmentRequestSchema)` to create a new message. + */ +export const RejectNodeScepEnrollmentRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_cryptos_fleet_v1_fleet, 156); + +/** + * @generated from message cryptos.fleet.v1.RejectNodeScepEnrollmentResponse + */ +export type RejectNodeScepEnrollmentResponse = Message<"cryptos.fleet.v1.RejectNodeScepEnrollmentResponse"> & { + /** + * enrollment is the rejected enrolment, now out of the queue. + * + * @generated from field: cryptos.fleet.v1.NodeScepEnrollment enrollment = 1; + */ + enrollment?: NodeScepEnrollment | undefined; +}; + +/** + * Describes the message cryptos.fleet.v1.RejectNodeScepEnrollmentResponse. + * Use `create(RejectNodeScepEnrollmentResponseSchema)` to create a new message. + */ +export const RejectNodeScepEnrollmentResponseSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_cryptos_fleet_v1_fleet, 157); + /** * Health reports the manager's view of node reachability, independent of * the node's own reported identity state. @@ -5807,6 +6044,30 @@ export const FleetService: GenService<{ input: typeof RevokeNodeScepChallengeRequestSchema; output: typeof RevokeNodeScepChallengeResponseSchema; }, + /** + * @generated from rpc cryptos.fleet.v1.FleetService.ListNodeScepEnrollments + */ + listNodeScepEnrollments: { + methodKind: "unary"; + input: typeof ListNodeScepEnrollmentsRequestSchema; + output: typeof ListNodeScepEnrollmentsResponseSchema; + }, + /** + * @generated from rpc cryptos.fleet.v1.FleetService.ApproveNodeScepEnrollment + */ + approveNodeScepEnrollment: { + methodKind: "unary"; + input: typeof ApproveNodeScepEnrollmentRequestSchema; + output: typeof ApproveNodeScepEnrollmentResponseSchema; + }, + /** + * @generated from rpc cryptos.fleet.v1.FleetService.RejectNodeScepEnrollment + */ + rejectNodeScepEnrollment: { + methodKind: "unary"; + input: typeof RejectNodeScepEnrollmentRequestSchema; + output: typeof RejectNodeScepEnrollmentResponseSchema; + }, }> = /*@__PURE__*/ serviceDesc(file_cryptos_fleet_v1_fleet, 0);