|
| 1 | +# Feature patch (cc-tdx v1.0) based on tag 0.5.20: Introducing support for confidential computing VMs on TDX |
| 2 | + |
| 3 | +diff --git a/external/acs-attest-client/index.js b/external/acs-attest-client/index.js |
| 4 | +index 36eaf8113..1ab63e547 100644 |
| 5 | +--- a/external/acs-attest-client/index.js |
| 6 | ++++ b/external/acs-attest-client/index.js |
| 7 | +@@ -25,8 +25,14 @@ import axios from 'axios'; |
| 8 | + import jsonwebtoken from 'jsonwebtoken'; |
| 9 | + import jwksClient from 'jwks-rsa'; |
| 10 | + import { jwtDecode } from 'jwt-decode'; |
| 11 | ++import { attest_adr,verify_adr, typeflag } from '../../src/lib/stores/index.ts'; |
| 12 | + |
| 13 | +-const ATTEST_SERVICE_ENDPOINT = "https://attest.cn-beijing.aliyuncs.com/v1/attestation"; |
| 14 | ++let ATTEST_SERVICE_ENDPOINT; |
| 15 | ++let verifyToken; |
| 16 | ++let ast_type; |
| 17 | ++attest_adr.subscribe(value => (ATTEST_SERVICE_ENDPOINT = value)); |
| 18 | ++verify_adr.subscribe(value => (verifyToken = value)); |
| 19 | ++typeflag.subscribe(value => (ast_type =value)); |
| 20 | + |
| 21 | + export async function attest(quote) { |
| 22 | + const quotebase64 = Buffer.from(quote).toString('base64'); |
| 23 | +@@ -58,7 +64,8 @@ export async function decode_apprasial_token(token) { |
| 24 | + |
| 25 | + export async function verify_apprasial_token(token) { |
| 26 | + const client = jwksClient({ |
| 27 | +- jwksUri: 'https://attest.cn-beijing.aliyuncs.com/jwks.json', |
| 28 | ++ // jwksUri: 'https://attest.cn-beijing.aliyuncs.com/jwks.json', |
| 29 | ++ jwksUrl: verifyToken |
| 30 | + }); |
| 31 | + const key = await client.getSigningKey(); |
| 32 | + const publicKey = key.getPublicKey(); |
| 33 | +diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte |
| 34 | +index c7e99c61d..644f0843c 100644 |
| 35 | +--- a/src/lib/components/chat/Chat.svelte |
| 36 | ++++ b/src/lib/components/chat/Chat.svelte |
| 37 | +@@ -89,6 +89,7 @@ |
| 38 | + import Placeholder from './Placeholder.svelte'; |
| 39 | + import NotificationToast from '../NotificationToast.svelte'; |
| 40 | + import Spinner from '../common/Spinner.svelte'; |
| 41 | ++ import { typeflag,attest_adr } from '$lib/stores'; |
| 42 | + |
| 43 | + export let chatIdProp = ''; |
| 44 | + |
| 45 | +@@ -646,6 +647,11 @@ |
| 46 | + }; |
| 47 | + |
| 48 | + // TEE Quote Verification Function |
| 49 | ++ let attestAdress; |
| 50 | ++ attest_adr.subscribe(value => (attestAdress = value)); |
| 51 | ++ let attestType; |
| 52 | ++ typeflag.subscribe(value => (attestType = value)); |
| 53 | ++ |
| 54 | + let _pendingQuoteUpdate = false; |
| 55 | + const teeQuoteVerify = async () => { |
| 56 | + const ENABLE_TEE = true; |
| 57 | +diff --git a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte |
| 58 | +index 59d230d1b..c4176f59a 100644 |
| 59 | +--- a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte |
| 60 | ++++ b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte |
| 61 | +@@ -2,6 +2,7 @@ |
| 62 | + import Switch from '$lib/components/common/Switch.svelte'; |
| 63 | + import Tooltip from '$lib/components/common/Tooltip.svelte'; |
| 64 | + import { getContext, createEventDispatcher } from 'svelte'; |
| 65 | ++ import { onMount, onDestroy } from "svelte"; |
| 66 | + |
| 67 | + const dispatch = createEventDispatcher(); |
| 68 | + |
| 69 | +@@ -12,6 +13,8 @@ |
| 70 | + export let params = { |
| 71 | + // Advanced |
| 72 | + stream_response: null, // Set stream responses for this model individually |
| 73 | ++ attestation: 'disable', |
| 74 | ++ attestationtype: null, |
| 75 | + function_calling: null, |
| 76 | + seed: null, |
| 77 | + stop: null, |
| 78 | +@@ -41,9 +44,53 @@ |
| 79 | + let customFieldName = ''; |
| 80 | + let customFieldValue = ''; |
| 81 | + |
| 82 | ++ import { models, settings, theme, user } from '$lib/stores'; |
| 83 | + $: if (params) { |
| 84 | + dispatch('change', params); |
| 85 | + } |
| 86 | ++ |
| 87 | ++ params = { ...params, ...$settings.params }; |
| 88 | ++ |
| 89 | ++ import { typeflag,attest_adr } from '$lib/stores'; |
| 90 | ++ import Chat from '$lib/components/chat/Chat.svelte'; |
| 91 | ++ let ATTEST_SERVICE_ENDPOINT; |
| 92 | ++ attest_adr.subscribe(value => (ATTEST_SERVICE_ENDPOINT = value)); |
| 93 | ++ let att_type; |
| 94 | ++ typeflag.subscribe(value => (att_type = value)); |
| 95 | ++ |
| 96 | ++ let selectedValue = 'ali'; |
| 97 | ++ let ali_input = ATTEST_SERVICE_ENDPOINT; |
| 98 | ++ let trustee_input = ''; |
| 99 | ++ let showInput = true; |
| 100 | ++ function handleSelectChange(event) { |
| 101 | ++ selectedValue = event.target.value; |
| 102 | ++ if (selectedValue === 'ali'){ |
| 103 | ++ showInput = true; |
| 104 | ++ params.attestationtype = 'ali'; |
| 105 | ++ attest_adr.set(ali_input); |
| 106 | ++ typeflag.set("Ali") |
| 107 | ++ } |
| 108 | ++ else if (selectedValue === 'trustee'){ |
| 109 | ++ showInput = true; |
| 110 | ++ params.attestationtype = 'trustee'; |
| 111 | ++ attest_adr.set(trustee_input); |
| 112 | ++ typeflag.set("trustee") |
| 113 | ++ } |
| 114 | ++ else { |
| 115 | ++ showInput = false; |
| 116 | ++ params.attestationtype = value; |
| 117 | ++ } |
| 118 | ++ $settings.params = {...$settings.params, ...params}; |
| 119 | ++ } |
| 120 | ++ |
| 121 | ++ |
| 122 | ++ function handleCustomInput() { |
| 123 | ++ if (customInput.trim()) { |
| 124 | ++ selectedValue = customInput; |
| 125 | ++ showInput = false; |
| 126 | ++ } |
| 127 | ++ } |
| 128 | ++ |
| 129 | + </script> |
| 130 | + |
| 131 | + <div class=" space-y-1 text-xs pb-safe-bottom"> |
| 132 | +@@ -129,7 +176,8 @@ |
| 133 | + class="p-1 px-3 text-xs flex rounded-sm transition shrink-0 outline-hidden" |
| 134 | + type="button" |
| 135 | + on:click={() => { |
| 136 | +- params.seed = (params?.seed ?? null) === null ? 0 : null; |
| 137 | ++ params.seed = (params?.seed ?? null) === null ? 0 : params.seed; |
| 138 | ++ $settings.params = {...$settings.params, ...params}; |
| 139 | + }} |
| 140 | + > |
| 141 | + {#if (params?.seed ?? null) === null} |
| 142 | +@@ -149,6 +197,7 @@ |
| 143 | + type="number" |
| 144 | + placeholder={$i18n.t('Enter Seed')} |
| 145 | + bind:value={params.seed} |
| 146 | ++ on:change={(e) => {$settings.params.seed=params.seed}} |
| 147 | + autocomplete="off" |
| 148 | + min="0" |
| 149 | + /> |
| 150 | +@@ -1170,6 +1219,108 @@ |
| 151 | + {/if} |
| 152 | + </div> |
| 153 | + |
| 154 | ++ <div> |
| 155 | ++ <Tooltip |
| 156 | ++ content={$i18n.t( |
| 157 | ++ 'When enabled, the chat session will attestate the remote environment running model service. Local: using local quote verification service, Remote: using remote verifiation service, need to configure Remote Verfication Service Address. Now only Intel TDX support.' |
| 158 | ++ )} |
| 159 | ++ placement="top-start" |
| 160 | ++ className="inline-tooltip" |
| 161 | ++ > |
| 162 | ++ <div class=" py-0.5 flex w-full justify-between"> |
| 163 | ++ <div class=" self-center text-xs font-medium"> |
| 164 | ++ {$i18n.t('Remote Attestation Mode')} |
| 165 | ++ </div> |
| 166 | ++ <button |
| 167 | ++ class="flex items-center px-3 py-1 rounded-sm transition-colors text-xs" |
| 168 | ++ class:bg-red-100={params?.attestation === 'disable'} |
| 169 | ++ class:dark:bg-red-800={params.attestation === 'disable'} |
| 170 | ++ class:text-red-700={params.attestation === 'disable'} |
| 171 | ++ class:dark:text-red-200={params.attestation === 'disable'} |
| 172 | ++ |
| 173 | ++ class:bg-green-100={params.attestation === 'enable'} |
| 174 | ++ class:dark:bg-green-800={params.attestation === 'enable'} |
| 175 | ++ class:text-green-700={params.attestation === 'enable'} |
| 176 | ++ class:dark:text-green-200={params.attestation === 'enable'} |
| 177 | ++ |
| 178 | ++ on:click={() => { |
| 179 | ++ params.attestation = params.attestation === 'disable' ? 'enable' : 'disable'; |
| 180 | ++ $settings.params = {...$settings.params, ...params}; |
| 181 | ++ }} |
| 182 | ++ type="button" |
| 183 | ++ > |
| 184 | ++ <span class="ml-2"> |
| 185 | ++ {#if params.attestation === 'disable'} |
| 186 | ++ {$i18n.t('Disable')} |
| 187 | ++ {:else} |
| 188 | ++ {$i18n.t('Enable')} |
| 189 | ++ {/if} |
| 190 | ++ </span> |
| 191 | ++ </button> |
| 192 | ++ </div> |
| 193 | ++ </Tooltip> |
| 194 | ++ </div> |
| 195 | ++ |
| 196 | ++ |
| 197 | ++ <div class=" py-0.5 w-full justify-between"> |
| 198 | ++ <Tooltip |
| 199 | ++ content={$i18n.t( |
| 200 | ++ 'Sets attestation Type. Default as Ali' |
| 201 | ++ )} |
| 202 | ++ placement="top-start" |
| 203 | ++ className="inline-tooltip" |
| 204 | ++ > |
| 205 | ++ <div class="flex w-full justify-between"> |
| 206 | ++ <div class=" self-center text-xs font-medium"> |
| 207 | ++ {$i18n.t('Attesation Service Type')} |
| 208 | ++ </div> |
| 209 | ++ <style> |
| 210 | ++ select { |
| 211 | ++ padding-right: 1px; |
| 212 | ++ width: 60px; |
| 213 | ++ height: 25px; |
| 214 | ++ font-size: 14px; |
| 215 | ++ } |
| 216 | ++ </style> |
| 217 | ++ |
| 218 | ++ <select |
| 219 | ++ disabled={(params?.attestation ?? null) === 'disable' ? true : false} |
| 220 | ++ bind:value={selectedValue} on:change={handleSelectChange}> |
| 221 | ++ <option value="ali"><span class="ml-2 self-center"> Ali </span></option> |
| 222 | ++ <option value="trustee"><span class="ml-2 self-center"> Trustee </span></option> |
| 223 | ++ </select> |
| 224 | ++ </div> |
| 225 | ++ </Tooltip> |
| 226 | ++ |
| 227 | ++ {#if (params?.attestationtype ?? null) !== null} |
| 228 | ++ {#if (params.attestationtype === 'ali') && showInput} |
| 229 | ++ <div class="flex mt-0.5 space-x-2"> |
| 230 | ++ <div class=" flex-1"> |
| 231 | ++ <input |
| 232 | ++ class="w-full rounded-lg py-2 px-1 text-sm dark:text-gray-300 dark:bg-gray-850 outline-hidden" |
| 233 | ++ type="text" |
| 234 | ++ bind:value={ali_input} |
| 235 | ++ autocomplete="off" |
| 236 | ++ /> |
| 237 | ++ </div> |
| 238 | ++ </div> |
| 239 | ++ {:else} |
| 240 | ++ <div class="flex mt-0.5 space-x-2"> |
| 241 | ++ <div class=" flex-1"> |
| 242 | ++ <input |
| 243 | ++ class="w-full rounded-lg py-2 px-1 text-sm dark:text-gray-300 dark:bg-gray-850 outline-hidden" |
| 244 | ++ type="text" |
| 245 | ++ placeholder='http://127.0.0.1:9090/verify_quote/trustee' |
| 246 | ++ bind:value={trustee_input} |
| 247 | ++ autocomplete="off" |
| 248 | ++ /> |
| 249 | ++ </div> |
| 250 | ++ </div> |
| 251 | ++ |
| 252 | ++ {/if} |
| 253 | ++ {/if} |
| 254 | ++ </div> |
| 255 | ++ |
| 256 | + {#if admin} |
| 257 | + <div class=" py-0.5 w-full justify-between"> |
| 258 | + <Tooltip |
| 259 | +diff --git a/src/lib/components/chat/Settings/General.svelte b/src/lib/components/chat/Settings/General.svelte |
| 260 | +index 666256c09..74c5ed4f5 100644 |
| 261 | +--- a/src/lib/components/chat/Settings/General.svelte |
| 262 | ++++ b/src/lib/components/chat/Settings/General.svelte |
| 263 | +@@ -371,7 +371,9 @@ |
| 264 | + use_mmap: params.use_mmap !== null ? params.use_mmap : undefined, |
| 265 | + use_mlock: params.use_mlock !== null ? params.use_mlock : undefined, |
| 266 | + num_thread: params.num_thread !== null ? params.num_thread : undefined, |
| 267 | +- num_gpu: params.num_gpu !== null ? params.num_gpu : undefined |
| 268 | ++ num_gpu: params.num_gpu !== null ? params.num_gpu : undefined, |
| 269 | ++ attestation: params.attestation !== null ? params.attestation : undefined, |
| 270 | ++ attestationtype: params.attestationtype !== null ? params.attestationtype : undefined |
| 271 | + }, |
| 272 | + keepAlive: keepAlive ? (isNaN(keepAlive) ? keepAlive : parseInt(keepAlive)) : undefined |
| 273 | + }); |
| 274 | +diff --git a/src/lib/stores/index.ts b/src/lib/stores/index.ts |
| 275 | +index 4526d3612..6bc11ad9f 100644 |
| 276 | +--- a/src/lib/stores/index.ts |
| 277 | ++++ b/src/lib/stores/index.ts |
| 278 | +@@ -5,7 +5,9 @@ import type { Banner } from '$lib/types'; |
| 279 | + import type { Socket } from 'socket.io-client'; |
| 280 | + |
| 281 | + import emojiShortCodes from '$lib/emoji-shortcodes.json'; |
| 282 | +- |
| 283 | ++export const typeflag = writable(); |
| 284 | ++export const attest_adr = writable("https://attest.cn-beijing.aliyuncs.com/v1/attestation"); |
| 285 | ++export const verify_adr = writable("https://attest.cn-beijing.aliyuncs.com/jwks.json"); |
| 286 | + // Backend |
| 287 | + export const WEBUI_NAME = writable(APP_NAME); |
| 288 | + export const config: Writable<Config | undefined> = writable(undefined); |
0 commit comments