1"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([["122832"],{870440(e,s,n){n.r(s),n.d(s,{metadata:()=>r,default:()=>h,frontMatter:()=>i,contentTitle:()=>a,toc:()=>d,assets:()=>l});var r=JSON.parse('{"id":"components/secret-stores/index","title":"Secret Stores","description":"Configure secret stores to manage sensitive data like passwords, tokens, and API keys.","source":"@site/versioned_docs/version-1.11.x/components/secret-stores/index.md","sourceDirName":"components/secret-stores","slug":"/components/secret-stores/","permalink":"/docs/v1.11/components/secret-stores/","draft":false,"unlisted":false,"editUrl":"https://github.com/spiceai/docs/edit/trunk/website/versioned_docs/version-1.11.x/components/secret-stores/index.md","tags":[],"version":"1.11.x","sidebarPosition":3,"frontMatter":{"title":"Secret Stores","sidebar_label":"Secret Stores","description":"Configure secret stores to manage sensitive data like passwords, tokens, and API keys.","image":"/img/og/secret-stores.png","sidebar_position":3,"pagination_prev":null,"pagination_next":null},"sidebar":"docs"}'),t=n(474848),c=n(28453),o=n(111315);let i={title:"Secret Stores",sidebar_label:"Secret Stores",description:"Configure secret stores to manage sensitive data like passwords, tokens, and API keys.",image:"/img/og/secret-stores.png",sidebar_position:3,pagination_prev:null,pagination_next:null},a,l={},d=[{value:"Default",id:"default",level:3},{value:"Configured Secret Stores",id:"configured-secret-stores",level:2},{value:"Using referenced secrets in component parameters",id:"using-secrets",level:2},{value:"Load secrets from multiple secret stores",id:"load-secrets-from-multiple-secret-stores",level:2},{value:"Secret Stores",id:"secret-stores",level:2}];function m(e){let s={a:"a",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,c.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.p,{children:"A Secret Store is a secure location where secrets (such as passwords, tokens, and API keys) are stored. Spice retrieves secrets from configured stores at runtime and injects them into component parameters."}),"\n",(0,t.jsxs)(s.p,{children:["Supported secret stores include: ",(0,t.jsx)(s.a,{href:"secret-stores/env",children:(0,t.jsx)(s.code,{children:"env"})}),", ",(0,t.jsx)(s.a,{href:"secret-stores/kubernetes",children:(0,t.jsx)(s.code,{children:"kubernetes"})}),", ",(0,t.jsx)(s.a,{href:"secret-stores/keyring",children:(0,t.jsx)(s.code,{children:"keyring"})}),", and ",(0,t.jsx)(s.a,{href:"secret-stores/aws-secrets-manager",children:(0,t.jsx)(s.code,{children:"aws_secrets_manager"})}),". The ",(0,t.jsx)(s.code,{children:"env"})," secret store is loaded by default."]}),"\n",(0,t.jsx)(s.h3,{id:"default",children:"Default"}),"\n",(0,t.jsxs)(s.p,{children:["The ",(0,t.jsx)(s.code,{children:"env"})," secret store is loaded by default. It reads secrets from environment variables and any ",(0,t.jsx)(s.code,{children:".env.local"})," or ",(0,t.jsx)(s.code,{children:".env"})," files in the project directory."]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-yaml",children:"secrets:\n - from: env\n name: env\n"})}),"\n",(0,t.jsx)(s.h2,{id:"configured-secret-stores",children:"Configured Secret Stores"}),"\n",(0,t.jsxs)(s.p,{children:["Secret Stores can be configured using the ",(0,t.jsx)(s.code,{children:"secrets"})," section of the ",(0,t.jsx)(s.code,{children:"spicepod.yml"})," file."]}),"\n",(0,t.jsxs)(s.p,{children:["The Secret Store type and name are specified using the ",(0,t.jsx)(s.code,{children:"from"})," and ",(0,t.jsx)(s.code,{children:"name"})," fields. The ",(0,t.jsx)(s.code,{children:"name"})," can be referenced by other components, like datasets or models. Some Secret Stores support adding a selector delimited by a colon (",(0,t.jsx)(s.code,{children:":"}),"), For example, when using the Kubernetes Secret Store, ",(0,t.jsx)(s.code,{children:"from: kubernetes:my_secret"})," selects and enables the ",(0,t.jsx)(s.code,{children:"my_secret"})," secret only to be referenced."]}),"\n",(0,t.jsxs)(s.p,{children:["Additional parameters may be specified in the ",(0,t.jsx)(s.code,{children:"params"})," field, which are typically specific to the secret store type."]}),"\n",(0,t.jsx)(s.p,{children:"Example:"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-yaml",children:"secrets:\n - from: kubernetes:my_secret\n name: k8s\n - from: env\n name: env\n"})}),"\n",(0,t.jsx)(s.h2,{id:"using-secrets",children:"Using referenced secrets in component parameters"}),"\n",(0,t.jsxs)(s.p,{children:["Secrets may be used by components with the syntax ",(0,t.jsx)(s.code,{children:"${<secret_store_name>:<key_name>}"}),". For example, to reference a secret stored as an environment variable named ",(0,t.jsx)(s.code,{children:"MY_SECRET"})," in the ",(0,t.jsx)(s.code,{children:"env"})," secret store, use ",(0,t.jsx)(s.code,{children:"${env:MY_SECRET}"}),"."]}),"\n",(0,t.jsx)(s.p,{children:"Example:"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-yaml",children:"datasets:\n - from: postgres:my_table\n name: my_table\n params:\n pg_host: localhost\n pg_port: 5432\n pg_user: ${env:PG_USER}\n pg_pass: ${env:FOO_PASSWORD} # The environment variable name may differ from the parameter name.\n"})}),"\n",(0,t.jsx)(s.p,{children:"This syntax also works within a larger string, like a connection string:"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-yaml",children:"datasets:\n - from: mysql:my_table\n name: my_table\n params:\n mysql_connection_string: mysql://${env:USER}:${env:PASSWORD}@localhost:3306/mysql_db\n"})}),"\n",(0,t.jsxs)(s.p,{children:["The ",(0,t.jsx)(s.code,{children:"<secret_store_name>"})," value in ",(0,t.jsx)(s.code,{children:"${<secret_store_name>:<key_name>}"})," is the ",(0,t.jsx)(s.code,{children:"name"})," value defined in the secret store configuration. This can be renamed to any value."]}),"\n",(0,t.jsx)(s.p,{children:"Example:"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-yaml",children:"secrets:\n - from: env\n name: my_env\n"})}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-yaml",children:"datasets:\n - from: postgres:my_table\n name: my_table\n params:\n pg_host: localhost\n pg_port: 5432\n pg_user: ${my_env:PG_USER}\n pg_pass: ${my_env:PG_PASS}\n"})}),"\n",(0,t.jsx)(s.h2,{id:"load-secrets-from-multiple-secret-stores",children:"Load secrets from multiple secret stores"}),"\n",(0,t.jsxs)(s.p,{children:["Spice supports configuring multiple secret stores which are loaded in the order they are defined in the ",(0,t.jsx)(s.code,{children:"secrets"})," section of the ",(0,t.jsx)(s.code,{children:"spicepod.yml"})," configuration file. If a secret is defined in multiple secret stores, the secret store defined last will take precedence."]}),"\n",(0,t.jsxs)(s.p,{children:["To load a secret from any of the configured secret stores in precedence order, use the ",(0,t.jsx)(s.code,{children:"${secrets:<key_name>}"})," syntax."]}),"\n",(0,t.jsx)(s.p,{children:"Example:"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-yaml",children:"secrets:\n - from: env\n name: env\n - from: keyring\n name: keyring\n"})}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-yaml",children:"datasets:\n - from: postgres:my_table\n name: my_table\n params:\n pg_host: localhost\n pg_port: 5432\n pg_user: ${secrets:pg_user}\n pg_pass: ${secrets:pg_pass}\n"})}),"\n",(0,t.jsxs)(s.p,{children:["In this example, the runtime would look for ",(0,t.jsx)(s.code,{children:"pg_user"})," and ",(0,t.jsx)(s.code,{children:"pg_pass"})," in the ",(0,t.jsx)(s.code,{children:"keyring"})," secret store first and then in the ",(0,t.jsx)(s.code,{children:"env"})," secret store. The ",(0,t.jsx)(s.code,{children:"<key_name>"})," value in ",(0,t.jsx)(s.code,{children:"${secrets:<key_name>}"})," is automatically uppercased for the ",(0,t.jsx)(s.code,{children:"env"})," secret store."]}),"\n",(0,t.jsxs)(s.p,{children:["To override the ",(0,t.jsx)(s.code,{children:"keyring"})," secret store secrets with environment variables, re-order the secret stores in the configuration file:"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-yaml",children:"secrets:\n - from: keyring\n name: keyring\n - from: env\n name: env\n"})}),"\n",(0,t.jsx)(s.h2,{id:"secret-stores",children:"Secret Stores"}),"\n","\n",(0,t.jsx)(o.A,{})]})}function h(e={}){let{wrapper:s}={...(0,c.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(m,{...e})}):m(e)}},111315(e,s,n){n.d(s,{A:()=>w});var r=n(474848);n(296540);var t=n(634164),c=n(588260);let o=new Intl.Segmenter(void 0,{granularity:"grapheme"});var i=n(330568),a=n(616497),l=n(358310),d=n(395310),m=n(588287),h=n(272072);function p({icon:e}){return(0,r.jsx)("span",{className:(0,t.A)(m.G.docs.docCard.icon,"cardTitleIcon_GcdP"),children:e})}function u({title:e}){return(0,r.jsx)("span",{className:(0,t.A)("text--truncate",m.G.docs.docCard.title,"cardTitleText_nuEl"),children:e})}function x({item:e,title:s,icon:n}){return(0,r.jsxs)(h.default,{as:"h2",className:(0,t.A)(m.G.docs.docCard.heading,"cardTitle_mcqP"),title:s,children:[n&&(0,r.jsx)(p,{item:e,icon:n}),(0,r.jsx)(u,{item:e,title:s})]})}function f({description:e}){return(0,r.jsx)("p",{className:(0,t.A)("text--truncate",m.G.docs.docCard.description,"cardDescription_L2fP"),title:e,children:e})}function g({className:e,href:s,children:n}){return(0,r.jsx)(d.default,{href:s,className:(0,t.A)("card padding--lg",m.G.docs.docCard.container,"cardContainer_KhuF",e),children:n})}function j({item:e,className:s,href:n,icon:t,title:c,description:o}){return(0,r.jsxs)(g,{href:n,className:s,children:[(0,r.jsx)(x,{item:e,icon:t,title:c}),o&&(0,r.jsx)(f,{item:e,description:o})]})}function y(e){var s;let n,r,t=(s=e.label,n=o.segment(s)[Symbol.iterator](),(r=n.next().value?.segment)&&RegExp("^\\p{RGI_Emoji}$","v").test(r)?{emoji:r,rest:s.slice(r.length)}:{emoji:null,rest:s});return{icon:t.emoji??("category"===e.type?"\u{1F5C3}":(0,l.A)(e.href)?"\u{1F4C4}\uFE0F":"\u{1F517}"),title:t.rest.trim()}}function v({item:e}){let s=(0,c.Nr)(e),n=function(){let{selectMessage:e}=(0,a.W)();return s=>e(s,(0,i.translate)({message:"1 item|{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:s}))}();return s?(0,r.jsx)(j,{item:e,className:e.className,href:s,description:e.description??n(e.items.length),...y(e)}):null}function _({item:e}){let s=(0,c.cC)(e.docId??void 0);return(0,r.jsx)(j,{item:e,className:e.className,href:e.href,description:e.description??s?.description,...y(e)})}function b({item:e}){switch(e.type){case"link":return(0,r.jsx)(_,{item:e});case"category":return(0,r.jsx)(v,{item:e});default:throw Error(`unknown item type ${JSON.stringify(e)}`)}}function S({className:e}){let s=(0,c.a4)();return(0,r.jsx)(w,{items:s,className:e})}function k({item:e}){return(0,r.jsx)("article",{className:(0,t.A)("docCardListItem_W1sv","col col--6"),children:(0,r.jsx)(b,{item:e})})}function w(e){let{items:s,className:n}=e;if(!s)return(0,r.jsx)(S,{...e});let o=(0,c.d1)(s);return(0,r.jsx)("section",{className:(0,t.A)("row",n),children:o.map((e,s)=>(0,r.jsx)(k,{item:e},s))})}},616497(e,s,n){n.d(s,{W:()=>a});var r=n(296540),t=n(610898);let c=["zero","one","two","few","many","other"];function o(e){return c.filter(s=>e.includes(s))}let i={locale:"en",pluralForms:o(["one","other"]),select:e=>1===e?"one":"other"};function a(){let e=function(){let{i18n:{currentLocale:e}}=(0,t.default)();return(0,r.useMemo)(()=>{try{let s;return s=new Intl.PluralRules(e),{locale:e,pluralForms:o(s.resolvedOptions().pluralCategories),select:e=>s.select(e)}}catch(s){return console.error(`Failed to use Intl.PluralRules for locale "${e}". 2Docusaurus will fallback to the default (English) implementation. 3Error: ${s.message} 4`),i}},[e])}();return{selectMessage:(s,n)=>(function(e,s,n){let r=e.split("|");if(1===r.length)return r[0];r.length>n.pluralForms.length&&console.error(`For locale=${n.locale}, a maximum of ${n.pluralForms.length} plural forms are expected (${n.pluralForms.join(",")}), but the message contains ${r.length}: ${e}`);let t=n.select(s);return r[Math.min(n.pluralForms.indexOf(t),r.length-1)]})(n,s,e)}}},28453(e,s,n){n.d(s,{R:()=>o,x:()=>i});var r=n(296540);let t={},c=r.createContext(t);function o(e){let s=r.useContext(c);return r.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function i(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),r.createElement(c.Provider,{value:s},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.