@voxgig/sdkgen 4.10.0 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/voxgig-sdkgen +1 -1
- package/package.json +1 -1
- package/project/.sdk/model/feature/secrets.aon +330 -0
- package/project/.sdk/model/target/c.aon +15 -2
- package/project/.sdk/model/target/cpp.aon +18 -0
- package/project/.sdk/model/target/lua.aon +17 -0
- package/project/.sdk/model/target/ocaml.aon +48 -5
- package/project/.sdk/model/target/zig.aon +30 -4
- package/project/.sdk/src/cmp/c/Config_c.ts +338 -1
- package/project/.sdk/src/cmp/c/Main_c.ts +57 -2
- package/project/.sdk/src/cmp/c/Package_c.ts +12 -2
- package/project/.sdk/src/cmp/cpp/Config_cpp.ts +324 -2
- package/project/.sdk/src/cmp/cpp/Gitignore_cpp.ts +2 -0
- package/project/.sdk/src/cmp/cpp/Main_cpp.ts +62 -4
- package/project/.sdk/src/cmp/cpp/Package_cpp.ts +10 -0
- package/project/.sdk/src/cmp/lua/Config_lua.ts +88 -0
- package/project/.sdk/src/cmp/lua/Gitignore_lua.ts +4 -0
- package/project/.sdk/src/cmp/lua/Main_lua.ts +93 -3
- package/project/.sdk/src/cmp/lua/Package_lua.ts +60 -0
- package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +10 -0
- package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +183 -5
- package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +160 -3
- package/project/.sdk/src/cmp/ocaml/Package_ocaml.ts +25 -1
- package/project/.sdk/src/cmp/zig/Config_zig.ts +130 -9
- package/project/.sdk/src/cmp/zig/Main_zig.ts +208 -4
- package/project/.sdk/{tm/zig/build.zig → src/cmp/zig/fragment/Build.fragment.zig} +7 -0
- package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +25 -0
- package/project/.sdk/{tm/zig/root.zig → src/cmp/zig/fragment/Root.fragment.zig} +9 -0
- package/project/.sdk/tm/c/Makefile +58 -9
- package/project/.sdk/tm/c/core/sdk.h +10 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/capability.c +133 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/capability.h +39 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/catalog.c +83 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/catalog.h +48 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/config.c +413 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/config.h +24 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/depend.c +264 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/depend.h +29 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/env.c +220 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/env.h +19 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/export.c +97 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/export.h +19 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/graph.c +237 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/graph.h +17 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/host.c +1494 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/host.h +135 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/order.c +288 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/order.h +18 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/point.c +141 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/point.h +80 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/ref.c +170 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/ref.h +52 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/resolve.c +98 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/resolve.h +18 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/types.c +150 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/types.h +104 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/value.c +649 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/value.h +135 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/version.c +151 -0
- package/project/.sdk/tm/c/feature/secrets/plugin/version.h +34 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/aws.c +281 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/azuresecrets.c +207 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/boru.c +164 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/clock.c +75 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/doppler.c +141 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/encode.c +144 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/gcpsecrets.c +177 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/hashicorp.c +239 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/httpjson.c +599 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/infisical.c +165 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/onepassword.c +194 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/proc.c +233 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/secretspec.c +125 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/sekretoplugins.h +125 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/sha256.c +270 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/sigv4.c +382 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/support.h +153 -0
- package/project/.sdk/tm/c/feature/secrets/plugins/tls.c +420 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/internal.h +86 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/json.c +721 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/providers.c +813 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/sekreto.c +944 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/sekreto.h +490 -0
- package/project/.sdk/tm/c/feature/secrets/sekreto/util.c +442 -0
- package/project/.sdk/tm/c/feature/secrets.c +797 -0
- package/project/.sdk/tm/c/feature/secrets.h +46 -0
- package/project/.sdk/tm/c/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/c/tests/feature/secrets/secrets_test.c +802 -0
- package/project/.sdk/tm/clojure/feature/secrets/sdk/feature/secrets.clj +38 -11
- package/project/.sdk/tm/clojure/test/sdk/test/feature/secrets.clj +40 -6
- package/project/.sdk/tm/cpp/Makefile +48 -4
- package/project/.sdk/tm/cpp/feature/secrets/plugin/capability.cpp +121 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/capability.hpp +41 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/catalog.cpp +60 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/catalog.hpp +66 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/config.cpp +376 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/config.hpp +29 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/depend.cpp +230 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/depend.hpp +31 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/env.cpp +205 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/env.hpp +25 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/export.cpp +84 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/export.hpp +24 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/graph.cpp +222 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/graph.hpp +21 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/host.cpp +1200 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/host.hpp +250 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/order.cpp +250 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/order.hpp +22 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/point.cpp +110 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/point.hpp +79 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/ref.cpp +136 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/ref.hpp +60 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/resolve.cpp +82 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/resolve.hpp +25 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/types.cpp +90 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/types.hpp +65 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/value.cpp +491 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/value.hpp +120 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/version.cpp +143 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugin/version.hpp +36 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Aws.cpp +248 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Aws.hpp +30 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Azuresecrets.cpp +149 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Azuresecrets.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Boru.cpp +117 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Boru.hpp +27 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Crypto.cpp +180 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Crypto.hpp +52 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Doppler.cpp +87 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Doppler.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Gcpsecrets.cpp +121 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Gcpsecrets.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Hashicorp.cpp +153 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Hashicorp.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Httpjson.cpp +666 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Httpjson.hpp +160 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Infisical.cpp +123 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Infisical.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Onepassword.cpp +125 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Onepassword.hpp +23 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Proc.cpp +223 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Proc.hpp +47 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Secretspec.cpp +104 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Secretspec.hpp +27 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Sigv4.cpp +242 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Sigv4.hpp +58 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Tls.cpp +260 -0
- package/project/.sdk/tm/cpp/feature/secrets/plugins/Tls.hpp +47 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Json.cpp +476 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Json.hpp +89 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Provider.cpp +312 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Provider.hpp +263 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Providers.cpp +354 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Providers.hpp +111 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Sekreto.cpp +613 -0
- package/project/.sdk/tm/cpp/feature/secrets/sekreto/Sekreto.hpp +227 -0
- package/project/.sdk/tm/cpp/feature/secrets.hpp +745 -0
- package/project/.sdk/tm/cpp/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/cpp/test/feature/secrets/secrets_test.cpp +808 -0
- package/project/.sdk/tm/csharp/feature/SecretsFeature.cs +34 -8
- package/project/.sdk/tm/csharp/test/feature/secrets/SecretsFeatureTest.cs +85 -0
- package/project/.sdk/tm/elixir/lib/projectname/feature/secrets.ex +17 -2
- package/project/.sdk/tm/elixir/test/feature/secrets/secrets_test.exs +41 -0
- package/project/.sdk/tm/go/feature/secrets_feature.go +32 -10
- package/project/.sdk/tm/go/test/feature/secrets/secrets_feature_test.go +116 -0
- package/project/.sdk/tm/java/feature/SecretsFeature.java +33 -8
- package/project/.sdk/tm/java/test/feature/secrets/SecretsFeatureTest.java +64 -0
- package/project/.sdk/tm/js/src/feature/secrets/SecretsFeature.js +34 -11
- package/project/.sdk/tm/js/test/feature/secrets/Secrets.test.js +73 -0
- package/project/.sdk/tm/kotlin/feature/SecretsFeature.kt +32 -7
- package/project/.sdk/tm/kotlin/test/feature/secrets/SecretsTest.kt +69 -0
- package/project/.sdk/tm/lua/Makefile +15 -4
- package/project/.sdk/tm/lua/feature/secrets/native/sekretonet.c +806 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/capability.lua +135 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/catalog.lua +63 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/config.lua +361 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/depend.lua +232 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/env.lua +168 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/export.lua +66 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/graph.lua +194 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/host.lua +1190 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/json.lua +169 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/order.lua +207 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/point.lua +106 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/ref.lua +115 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/resolve.lua +78 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/types.lua +275 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin/version.lua +131 -0
- package/project/.sdk/tm/lua/feature/secrets/plugin.lua +76 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/addr.lua +124 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/err.lua +47 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/name.lua +315 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/aws.lua +228 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/azuresecrets.lua +137 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/boru.lua +124 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/crypto.lua +212 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/doppler.lua +89 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/gcpsecrets.lua +129 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/hashicorp.lua +154 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/httpjson.lua +248 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/infisical.lua +113 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/json.lua +449 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/net.lua +198 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/onepassword.lua +126 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/secretspec.lua +93 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/sigv4.lua +269 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/plugins/support.lua +146 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto/providers.lua +346 -0
- package/project/.sdk/tm/lua/feature/secrets/sekreto.lua +479 -0
- package/project/.sdk/tm/lua/feature/secrets_feature.lua +690 -0
- package/project/.sdk/tm/lua/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/lua/test/extend_test.lua +105 -0
- package/project/.sdk/tm/lua/test/feature/secrets/secrets_feature_test.lua +862 -0
- package/project/.sdk/tm/ocaml/Makefile +52 -8
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/capability.ml +106 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/catalog.ml +43 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/config.ml +349 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/defs.ml +143 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/depend.ml +217 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/env.ml +197 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/export.ml +89 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/graph.ml +227 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/host.ml +1112 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/order.ml +202 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/point.ml +138 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/ref.ml +126 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/resolve.ml +62 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/types.ml +97 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/value.ml +387 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugin/version.ml +139 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/aws.ml +171 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/azuresecrets.ml +116 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/boru.ml +95 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/crypto.ml +149 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/doppler.ml +61 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/gcpsecrets.ml +93 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/hashicorp.ml +120 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/http.ml +421 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/httpjson.ml +66 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/infisical.ml +85 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/onepassword.ml +112 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/runcmd.ml +97 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/secretspec.ml +68 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/sigv4.ml +259 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/tls.ml +44 -0
- package/project/.sdk/tm/ocaml/feature/secrets/plugins/tls_stubs.c +358 -0
- package/project/.sdk/tm/ocaml/feature/secrets/sekreto/json.ml +376 -0
- package/project/.sdk/tm/ocaml/feature/secrets/sekreto/provider.ml +647 -0
- package/project/.sdk/tm/ocaml/feature/secrets/sekreto/secret.ml +299 -0
- package/project/.sdk/tm/ocaml/feature/secrets/sekreto/sekreto.ml +347 -0
- package/project/.sdk/tm/ocaml/feature/secrets_feature.ml +453 -0
- package/project/.sdk/tm/ocaml/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/ocaml/test/feature/secrets/t_secrets.ml +670 -0
- package/project/.sdk/tm/perl/feature/secrets_feature.pm +33 -12
- package/project/.sdk/tm/perl/t/feature/secrets/secrets.t +47 -0
- package/project/.sdk/tm/php/feature/SecretsFeature.php +30 -6
- package/project/.sdk/tm/php/test/feature/secrets/SecretsTest.php +98 -0
- package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +28 -6
- package/project/.sdk/tm/py/test/feature/secrets/test_secrets.py +114 -0
- package/project/.sdk/tm/rb/feature/secrets_feature.rb +28 -6
- package/project/.sdk/tm/rb/test/feature/secrets/secrets_feature_test.rb +93 -0
- package/project/.sdk/tm/rust/feature/secrets.rs +33 -10
- package/project/.sdk/tm/rust/tests/feature/secrets/main.rs +96 -0
- package/project/.sdk/tm/scala/feature/SecretsFeature.scala +29 -7
- package/project/.sdk/tm/scala/sdktest/feature/secrets/SecretsTestMain.scala +71 -0
- package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +35 -12
- package/project/.sdk/tm/ts/test/feature/secrets/Secrets.test.ts +73 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/capability.zig +137 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/catalog.zig +90 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/config.zig +346 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/depend.zig +244 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/env.zig +201 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/export.zig +83 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/graph.zig +212 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/host.zig +1224 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/inst.zig +126 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/order.zig +228 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/plugin.zig +34 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/point.zig +166 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/ref.zig +147 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/resolve.zig +74 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/types.zig +140 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/value.zig +662 -0
- package/project/.sdk/tm/zig/feature/secrets/plugin/version.zig +139 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/aws.zig +294 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/azuresecrets.zig +222 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/boru.zig +188 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/doppler.zig +135 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/gcpsecrets.zig +170 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/hashicorp.zig +242 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/httpjson.zig +535 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/infisical.zig +167 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/onepassword.zig +202 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/secretspec.zig +160 -0
- package/project/.sdk/tm/zig/feature/secrets/plugins/sigv4.zig +336 -0
- package/project/.sdk/tm/zig/feature/secrets/sekreto/addr.zig +148 -0
- package/project/.sdk/tm/zig/feature/secrets/sekreto/builtins.zig +259 -0
- package/project/.sdk/tm/zig/feature/secrets/sekreto/provider.zig +440 -0
- package/project/.sdk/tm/zig/feature/secrets/sekreto/sekreto.zig +944 -0
- package/project/.sdk/tm/zig/feature/secrets.zig +854 -0
- package/project/.sdk/tm/zig/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/zig/test/feature/secrets/secrets_test.zig +891 -0
- package/project/sdkgen-package.json +1 -1
|
@@ -0,0 +1,944 @@
|
|
|
1
|
+
// VENDORED: @voxgig/sekreto sdk-20260908-1556-0 (c/src/sekreto.c)
|
|
2
|
+
// Source: https://github.com/voxgig/sekreto @ 1267ee2e5f49566bc92695bc9eb3a60ef4924998 [tag: sdk-20260908-1556-0]
|
|
3
|
+
// License: MIT (c) voxgig - see repository LICENSE. Do not edit: resync from upstream.
|
|
4
|
+
/* sekreto: one interface for secrets, wherever they live.
|
|
5
|
+
*
|
|
6
|
+
* A Sekreto is an ordered chain of providers. `get` asks each in turn and
|
|
7
|
+
* returns the first hit, so an app can be configured from environment
|
|
8
|
+
* variables in development and a vault in production without changing a
|
|
9
|
+
* line of its own code.
|
|
10
|
+
*
|
|
11
|
+
* This file holds the facade and every pure name function, and it builds
|
|
12
|
+
* the chain on a voxgig/plugin host: each spec'd provider is an instance
|
|
13
|
+
* addressed by name+tag, `load` runs the kind's `define` and `activate`
|
|
14
|
+
* takes it live. Nothing here opens a socket, runs a child or touches a
|
|
15
|
+
* certificate - and neither does anything else under `src/`. The kinds
|
|
16
|
+
* that do are plugins under `plugins/`, and only a link line that names
|
|
17
|
+
* one carries them.
|
|
18
|
+
*
|
|
19
|
+
* A port of typescript/src/Sekreto.ts, which is canonical.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
#define _POSIX_C_SOURCE 200809L
|
|
23
|
+
|
|
24
|
+
#include <stdio.h>
|
|
25
|
+
#include <string.h>
|
|
26
|
+
|
|
27
|
+
#include "internal.h"
|
|
28
|
+
|
|
29
|
+
/* ---- names --------------------------------------------------------- */
|
|
30
|
+
|
|
31
|
+
/* Scanned character by character rather than matched against
|
|
32
|
+
* `^[a-z0-9_]+$`, and that is deliberate. In Python, PCRE, Perl and .NET
|
|
33
|
+
* `$` also matches before a final newline, so four ports accepted
|
|
34
|
+
* `api.token\n` as a valid name; the spec pins it, `api\n.token` and
|
|
35
|
+
* `api.token\r` as invalid. A scan cannot have that bug. */
|
|
36
|
+
int sek_validname(const char *name) {
|
|
37
|
+
size_t index;
|
|
38
|
+
size_t seglen = 0;
|
|
39
|
+
|
|
40
|
+
if (NULL == name || '\0' == name[0]) {
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
for (index = 0; '\0' != name[index]; index++) {
|
|
45
|
+
char ch = name[index];
|
|
46
|
+
|
|
47
|
+
if ('.' == ch) {
|
|
48
|
+
if (0 == seglen) {
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
seglen = 0;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!(('a' <= ch && 'z' >= ch) || ('0' <= ch && '9' >= ch) || '_' == ch)) {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
seglen++;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return 0 < seglen;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
sek_err sek_checkname(sek_pool *pool, const char *name) {
|
|
66
|
+
if (sek_validname(name)) {
|
|
67
|
+
return NULL;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* A NULL name renders as the empty string, so the message ends with a
|
|
71
|
+
* trailing space - which the spec pins, byte for byte. */
|
|
72
|
+
return sek_fmt(pool, "sekreto: invalid name: %s", sek_orempty(name));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* The segments of a name, which every function below wants. */
|
|
76
|
+
static sek_list *segments(sek_pool *pool, const char *name) {
|
|
77
|
+
sek_list *out = sek_list_new(pool);
|
|
78
|
+
const char *at = name;
|
|
79
|
+
|
|
80
|
+
for (;;) {
|
|
81
|
+
const char *dot = strchr(at, '.');
|
|
82
|
+
if (NULL == dot) {
|
|
83
|
+
sek_list_add(out, at);
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
sek_list_add(out, sek_strndup(pool, at, (size_t)(dot - at)));
|
|
87
|
+
at = dot + 1;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* The environment-variable key for a name: `api.token` -> `API_TOKEN`.
|
|
92
|
+
* The prefix is NOT uppercased - it arrives as configured. */
|
|
93
|
+
sek_err sek_envkey(sek_pool *pool, const char *name, const char *prefix, char **out) {
|
|
94
|
+
sek_err err = sek_checkname(pool, name);
|
|
95
|
+
sek_buf buf;
|
|
96
|
+
size_t index;
|
|
97
|
+
|
|
98
|
+
if (NULL != err) {
|
|
99
|
+
return err;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
sek_buf_init(&buf, pool);
|
|
103
|
+
sek_buf_add(&buf, sek_orempty(prefix));
|
|
104
|
+
|
|
105
|
+
for (index = 0; '\0' != name[index]; index++) {
|
|
106
|
+
sek_buf_addch(&buf, '.' == name[index] ? '_' : sek_upper(name[index]));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
*out = buf.data;
|
|
110
|
+
|
|
111
|
+
return NULL;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Where a name lives in a KV vault: `api.token` -> `api` / `token`. A
|
|
115
|
+
* single-segment name has no path of its own, so it becomes a secret of
|
|
116
|
+
* that name with the conventional field `value`. */
|
|
117
|
+
sek_err sek_vaultref_of(sek_pool *pool, const char *name, sek_vaultref *out) {
|
|
118
|
+
sek_err err = sek_checkname(pool, name);
|
|
119
|
+
sek_list *parts;
|
|
120
|
+
sek_buf path;
|
|
121
|
+
size_t index;
|
|
122
|
+
|
|
123
|
+
if (NULL != err) {
|
|
124
|
+
return err;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
parts = segments(pool, name);
|
|
128
|
+
|
|
129
|
+
if (1 == parts->len) {
|
|
130
|
+
out->path = parts->items[0];
|
|
131
|
+
out->field = sek_strdup(pool, "value");
|
|
132
|
+
return NULL;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
sek_buf_init(&path, pool);
|
|
136
|
+
for (index = 0; index + 1 < parts->len; index++) {
|
|
137
|
+
if (0 < index) {
|
|
138
|
+
sek_buf_addch(&path, '/');
|
|
139
|
+
}
|
|
140
|
+
sek_buf_add(&path, parts->items[index]);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
out->path = path.data;
|
|
144
|
+
out->field = parts->items[parts->len - 1];
|
|
145
|
+
|
|
146
|
+
return NULL;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* A name flattened to one segment: `api.token` -> `api_token` (GCP Secret
|
|
150
|
+
* Manager) or `api-token` (Azure Key Vault). With `-` as the separator
|
|
151
|
+
* underscores flatten too, because Key Vault's alphabet is letters,
|
|
152
|
+
* digits and hyphens only and `with_underscore` must still be
|
|
153
|
+
* representable there. */
|
|
154
|
+
sek_err sek_flatname(sek_pool *pool, const char *name, const char *sep, char **out) {
|
|
155
|
+
sek_err err = sek_checkname(pool, name);
|
|
156
|
+
sek_buf buf;
|
|
157
|
+
size_t index;
|
|
158
|
+
int hyphen;
|
|
159
|
+
|
|
160
|
+
if (NULL != err) {
|
|
161
|
+
return err;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
hyphen = NULL != sep && 0 == strcmp(sep, "-");
|
|
165
|
+
|
|
166
|
+
sek_buf_init(&buf, pool);
|
|
167
|
+
|
|
168
|
+
for (index = 0; '\0' != name[index]; index++) {
|
|
169
|
+
char ch = name[index];
|
|
170
|
+
if ('.' == ch) {
|
|
171
|
+
sek_buf_add(&buf, sek_orempty(sep));
|
|
172
|
+
} else if (hyphen && '_' == ch) {
|
|
173
|
+
sek_buf_addch(&buf, '-');
|
|
174
|
+
} else {
|
|
175
|
+
sek_buf_addch(&buf, ch);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
*out = buf.data;
|
|
180
|
+
|
|
181
|
+
return NULL;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* The AWS SSM Parameter Store name: dots become the path hierarchy,
|
|
185
|
+
* rooted at `/` or at a prefix. `db.pass.main` -> `/db/pass/main`. */
|
|
186
|
+
sek_err sek_awsparam(sek_pool *pool, const char *name, const char *prefix, char **out) {
|
|
187
|
+
sek_err err = sek_checkname(pool, name);
|
|
188
|
+
sek_buf buf;
|
|
189
|
+
const char *base = sek_orempty(prefix);
|
|
190
|
+
size_t index;
|
|
191
|
+
|
|
192
|
+
if (NULL != err) {
|
|
193
|
+
return err;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
sek_buf_init(&buf, pool);
|
|
197
|
+
|
|
198
|
+
if ('\0' != base[0]) {
|
|
199
|
+
size_t len = strlen(base);
|
|
200
|
+
if ('/' != base[0]) {
|
|
201
|
+
sek_buf_addch(&buf, '/');
|
|
202
|
+
}
|
|
203
|
+
if (0 < len && '/' == base[len - 1]) {
|
|
204
|
+
sek_buf_addn(&buf, base, len - 1);
|
|
205
|
+
} else {
|
|
206
|
+
sek_buf_add(&buf, base);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
sek_buf_addch(&buf, '/');
|
|
211
|
+
|
|
212
|
+
for (index = 0; '\0' != name[index]; index++) {
|
|
213
|
+
sek_buf_addch(&buf, '.' == name[index] ? '/' : name[index]);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
*out = buf.data;
|
|
217
|
+
|
|
218
|
+
return NULL;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* ---- .env ---------------------------------------------------------- */
|
|
222
|
+
|
|
223
|
+
/* `\n \r \t \\ \"` become their characters; ANY OTHER escape is preserved
|
|
224
|
+
* as backslash plus character, and a trailing backslash is literal. A
|
|
225
|
+
* scan, not a chain of replacements - a chain would rewrite the output of
|
|
226
|
+
* the step before it. */
|
|
227
|
+
static char *unescape(sek_pool *pool, const char *text, size_t len) {
|
|
228
|
+
sek_buf out;
|
|
229
|
+
size_t index = 0;
|
|
230
|
+
|
|
231
|
+
sek_buf_init(&out, pool);
|
|
232
|
+
|
|
233
|
+
while (index < len) {
|
|
234
|
+
if ('\\' == text[index] && index + 1 < len) {
|
|
235
|
+
char next = text[index + 1];
|
|
236
|
+
index += 2;
|
|
237
|
+
|
|
238
|
+
switch (next) {
|
|
239
|
+
case 'n':
|
|
240
|
+
sek_buf_addch(&out, '\n');
|
|
241
|
+
break;
|
|
242
|
+
case 'r':
|
|
243
|
+
sek_buf_addch(&out, '\r');
|
|
244
|
+
break;
|
|
245
|
+
case 't':
|
|
246
|
+
sek_buf_addch(&out, '\t');
|
|
247
|
+
break;
|
|
248
|
+
case '\\':
|
|
249
|
+
sek_buf_addch(&out, '\\');
|
|
250
|
+
break;
|
|
251
|
+
case '"':
|
|
252
|
+
sek_buf_addch(&out, '"');
|
|
253
|
+
break;
|
|
254
|
+
default:
|
|
255
|
+
sek_buf_addch(&out, '\\');
|
|
256
|
+
sek_buf_addch(&out, next);
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
sek_buf_addch(&out, text[index]);
|
|
264
|
+
index++;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return out.data;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
static char *trim(sek_pool *pool, const char *text, size_t len) {
|
|
271
|
+
size_t start = 0;
|
|
272
|
+
size_t end = len;
|
|
273
|
+
|
|
274
|
+
while (start < end && (' ' == text[start] || '\t' == text[start] || '\r' == text[start] ||
|
|
275
|
+
'\n' == text[start] || '\v' == text[start] || '\f' == text[start])) {
|
|
276
|
+
start++;
|
|
277
|
+
}
|
|
278
|
+
while (end > start && (' ' == text[end - 1] || '\t' == text[end - 1] || '\r' == text[end - 1] ||
|
|
279
|
+
'\n' == text[end - 1] || '\v' == text[end - 1] || '\f' == text[end - 1])) {
|
|
280
|
+
end--;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return sek_strndup(pool, text + start, end - start);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* Deliberately small: `KEY=value`, optional `export`, `#` comments on
|
|
287
|
+
* their own line, and single- or double-quoted values. There is no `.env`
|
|
288
|
+
* standard, so this function IS the specification, and every clause of it
|
|
289
|
+
* is pinned by the corpus. */
|
|
290
|
+
sek_map *sek_parsedotenv(sek_pool *pool, const char *text) {
|
|
291
|
+
sek_map *out = sek_map_new(pool);
|
|
292
|
+
const char *at;
|
|
293
|
+
|
|
294
|
+
if (NULL == text) {
|
|
295
|
+
return out;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
at = text;
|
|
299
|
+
|
|
300
|
+
for (;;) {
|
|
301
|
+
const char *nl = strchr(at, '\n');
|
|
302
|
+
size_t rawlen = NULL == nl ? strlen(at) : (size_t)(nl - at);
|
|
303
|
+
char *line;
|
|
304
|
+
const char *body;
|
|
305
|
+
const char *eq;
|
|
306
|
+
char *key;
|
|
307
|
+
char *value;
|
|
308
|
+
size_t vlen;
|
|
309
|
+
|
|
310
|
+
/* One trailing `\r`, then the whole line trimmed. */
|
|
311
|
+
if (0 < rawlen && '\r' == at[rawlen - 1]) {
|
|
312
|
+
rawlen--;
|
|
313
|
+
}
|
|
314
|
+
line = trim(pool, at, rawlen);
|
|
315
|
+
|
|
316
|
+
if ('\0' == line[0] || '#' == line[0]) {
|
|
317
|
+
goto next;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/* A literal leading `export `, then a re-trim. */
|
|
321
|
+
body = sek_has_prefix(line, "export ") ? trim(pool, line + 7, strlen(line + 7)) : line;
|
|
322
|
+
|
|
323
|
+
eq = strchr(body, '=');
|
|
324
|
+
/* Both "no `=`" and "empty key" are skipped silently, without
|
|
325
|
+
* abandoning the rest of the file. */
|
|
326
|
+
if (NULL == eq || eq == body) {
|
|
327
|
+
goto next;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
key = trim(pool, body, (size_t)(eq - body));
|
|
331
|
+
value = trim(pool, eq + 1, strlen(eq + 1));
|
|
332
|
+
vlen = strlen(value);
|
|
333
|
+
|
|
334
|
+
if (2 <= vlen && '"' == value[0] && '"' == value[vlen - 1]) {
|
|
335
|
+
value = unescape(pool, value + 1, vlen - 2);
|
|
336
|
+
} else if (2 <= vlen && '\'' == value[0] && '\'' == value[vlen - 1]) {
|
|
337
|
+
value = sek_strndup(pool, value + 1, vlen - 2);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* Keys verbatim, no case folding; a later duplicate overwrites. */
|
|
341
|
+
sek_map_set(out, key, value);
|
|
342
|
+
|
|
343
|
+
next:
|
|
344
|
+
if (NULL == nl) {
|
|
345
|
+
return out;
|
|
346
|
+
}
|
|
347
|
+
at = nl + 1;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/* ---- redact -------------------------------------------------------- */
|
|
352
|
+
|
|
353
|
+
/* Only values of four characters or more are replaced: shorter ones are
|
|
354
|
+
* too likely to appear in ordinary text, and redacting them would make
|
|
355
|
+
* logs unreadable without making them safer.
|
|
356
|
+
*
|
|
357
|
+
* Longest first, always. The corpus pins both arrival orders of
|
|
358
|
+
* ['abcd','abcd1234'] against `token=abcd1234`, so the case cannot pass
|
|
359
|
+
* by luck - the short value would otherwise chew the long one in half.
|
|
360
|
+
*
|
|
361
|
+
* The sort is over a COPY: the caller's list is `seen` when this is
|
|
362
|
+
* reached through sek_redact_text, and sorting in place would reorder the
|
|
363
|
+
* live redaction history. */
|
|
364
|
+
char *sek_redact(sek_pool *pool, const char *text, const sek_list *values) {
|
|
365
|
+
sek_list *usable = sek_list_new(pool);
|
|
366
|
+
char *out = sek_strdup(pool, NULL == text ? "" : text);
|
|
367
|
+
size_t index;
|
|
368
|
+
|
|
369
|
+
if (NULL == values) {
|
|
370
|
+
return out;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
for (index = 0; index < values->len; index++) {
|
|
374
|
+
if (NULL != values->items[index] && 4 <= strlen(values->items[index])) {
|
|
375
|
+
sek_list_add(usable, values->items[index]);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
for (index = 1; index < usable->len; index++) {
|
|
380
|
+
char *value = usable->items[index];
|
|
381
|
+
size_t back = index;
|
|
382
|
+
|
|
383
|
+
while (0 < back && strlen(usable->items[back - 1]) < strlen(value)) {
|
|
384
|
+
usable->items[back] = usable->items[back - 1];
|
|
385
|
+
back--;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
usable->items[back] = value;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
for (index = 0; index < usable->len; index++) {
|
|
392
|
+
const char *value = usable->items[index];
|
|
393
|
+
size_t vlen = strlen(value);
|
|
394
|
+
sek_buf next;
|
|
395
|
+
const char *rest = out;
|
|
396
|
+
|
|
397
|
+
sek_buf_init(&next, pool);
|
|
398
|
+
|
|
399
|
+
/* A literal substring replace-all, never a regex: a secret containing
|
|
400
|
+
* metacharacters must not be interpreted as a pattern. */
|
|
401
|
+
for (;;) {
|
|
402
|
+
const char *found = strstr(rest, value);
|
|
403
|
+
if (NULL == found) {
|
|
404
|
+
sek_buf_add(&next, rest);
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
sek_buf_addn(&next, rest, (size_t)(found - rest));
|
|
408
|
+
sek_buf_add(&next, "[redacted]");
|
|
409
|
+
rest = found + vlen;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
out = next.data;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return out;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* ---- the chain ----------------------------------------------------- */
|
|
419
|
+
|
|
420
|
+
/* The store name a provider answers to when nothing says otherwise.
|
|
421
|
+
* describe() opens with the provider's kind - `hashicorp:...`,
|
|
422
|
+
* `dotenv:...`, plain `env` - so the kind is the natural default. */
|
|
423
|
+
char *sek_storename(sek_pool *pool, sek_provider *provider) {
|
|
424
|
+
const char *text = provider->describe(provider);
|
|
425
|
+
const char *colon = strchr(text, ':');
|
|
426
|
+
|
|
427
|
+
return NULL == colon ? sek_strdup(pool, text) : sek_strndup(pool, text, (size_t)(colon - text));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
typedef struct {
|
|
431
|
+
char *store;
|
|
432
|
+
/* The plugin instance that built this provider - "" for one handed in
|
|
433
|
+
* already built, which no instance backs. */
|
|
434
|
+
const char *ref;
|
|
435
|
+
sek_provider *provider;
|
|
436
|
+
} entry;
|
|
437
|
+
|
|
438
|
+
typedef struct {
|
|
439
|
+
char *store;
|
|
440
|
+
char *name;
|
|
441
|
+
char *value;
|
|
442
|
+
} cached;
|
|
443
|
+
|
|
444
|
+
struct sek_sekreto {
|
|
445
|
+
sek_pool *pool;
|
|
446
|
+
|
|
447
|
+
/* The voxgig/plugin host every spec'd provider is an instance of, and
|
|
448
|
+
* the catalog of definitions it can build: the built-ins, then whatever
|
|
449
|
+
* sek_options.plugins handed in. */
|
|
450
|
+
Host *host;
|
|
451
|
+
Catalog *catalog;
|
|
452
|
+
|
|
453
|
+
entry *entries;
|
|
454
|
+
size_t count;
|
|
455
|
+
int docache;
|
|
456
|
+
|
|
457
|
+
cached *cache;
|
|
458
|
+
size_t cachelen;
|
|
459
|
+
size_t cachecap;
|
|
460
|
+
|
|
461
|
+
/* Every value ever resolved, for redaction. Kept independently of the
|
|
462
|
+
* read cache, so `nocache` does not silently disable sek_redact_text
|
|
463
|
+
* and leak secrets to logs, and append-only for the object's life: not
|
|
464
|
+
* cleared by sek_refresh, not cleared by sek_close. */
|
|
465
|
+
sek_list *seen;
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
Host *sek_host(sek_sekreto *sek) { return sek->host; }
|
|
469
|
+
|
|
470
|
+
Catalog *sek_catalog(sek_sekreto *sek) { return sek->catalog; }
|
|
471
|
+
|
|
472
|
+
/* The message for a kind the catalog does not hold.
|
|
473
|
+
*
|
|
474
|
+
* A kind sekreto has never heard of is a typo; a kind that exists as a
|
|
475
|
+
* plugin but was not passed in is the split working as designed and
|
|
476
|
+
* telling you what to pass. Collapsing the two was the first thing that
|
|
477
|
+
* made the split confusing to use. */
|
|
478
|
+
static sek_err unknownkind(sek_pool *pool, const char *kind, Catalog *catalog) {
|
|
479
|
+
Value *names = catalog_names(catalog);
|
|
480
|
+
sek_buf out;
|
|
481
|
+
size_t index;
|
|
482
|
+
|
|
483
|
+
sek_buf_init(&out, pool);
|
|
484
|
+
sek_buf_addfmt(&out, "sekreto: unknown provider kind: %s (available: ", kind);
|
|
485
|
+
|
|
486
|
+
for (index = 0; index < vlen(names); index++) {
|
|
487
|
+
if (0 < index) {
|
|
488
|
+
sek_buf_add(&out, ", ");
|
|
489
|
+
}
|
|
490
|
+
sek_buf_add(&out, vasstr(vat(names, index)));
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
sek_buf_addch(&out, ')');
|
|
494
|
+
|
|
495
|
+
for (index = 0; NULL != SEK_PLUGIN_KINDS[index]; index++) {
|
|
496
|
+
if (0 == strcmp(SEK_PLUGIN_KINDS[index], kind)) {
|
|
497
|
+
sek_buf_addfmt(&out,
|
|
498
|
+
" - %s is a sekreto plugin, not built in: pass it in the plugins option",
|
|
499
|
+
kind);
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
return out.data;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/* A sekreto refusal that crossed the plugin boundary, back as itself,
|
|
508
|
+
* byte for byte. Anything else is not sekreto's to rewrite and surfaces
|
|
509
|
+
* as the host reports it, naming the instance and the cause. */
|
|
510
|
+
static sek_err unwrap(sek_pool *pool, PluginError *err) {
|
|
511
|
+
if (NULL == err) {
|
|
512
|
+
return sek_strdup(pool, "sekreto: the plugin host failed without saying why");
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (NULL != err->code && 0 == strcmp(SEK_ERROR_CODE, err->code)) {
|
|
516
|
+
Value *cause = vget(err->details, "cause");
|
|
517
|
+
if (visstr(cause)) {
|
|
518
|
+
return sek_strdup(pool, vasstr(cause));
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
return sek_strdup(pool, err->message);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/* One chain entry, as a plugin instance.
|
|
526
|
+
*
|
|
527
|
+
* The instance is `kind` for a store named after its kind and
|
|
528
|
+
* `kind$store` otherwise - `hashicorp$prod` - so host_list reads like the
|
|
529
|
+
* chain. A store name that is already taken gets a numbered tag from the
|
|
530
|
+
* host instead, because two providers MAY share a store name (a directed
|
|
531
|
+
* read walks both) and an instance ref may not.
|
|
532
|
+
*
|
|
533
|
+
* Raises through voxgig/plugin's `fail` for anything the host refuses;
|
|
534
|
+
* sek_new is the frame that catches it. */
|
|
535
|
+
static sek_err declare(sek_sekreto *sek, const sek_spec *spec, entry *out) {
|
|
536
|
+
const char *kind = sek_orempty(spec->kind);
|
|
537
|
+
const char *store;
|
|
538
|
+
const char *ref;
|
|
539
|
+
DeclareSpec declared;
|
|
540
|
+
Value *exported;
|
|
541
|
+
sek_provider *provider;
|
|
542
|
+
|
|
543
|
+
if (!catalog_has(sek->catalog, kind)) {
|
|
544
|
+
return unknownkind(sek->pool, kind, sek->catalog);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
store = sek_empty(spec->name) ? kind : spec->name;
|
|
548
|
+
|
|
549
|
+
if (!checktag(vstr(store))) {
|
|
550
|
+
return sek_fmt(sek->pool, "sekreto: invalid store name: %s", store);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
ref = 0 == strcmp(store, kind) ? kind : formatref(vstr(kind), vstr(store));
|
|
554
|
+
if (NULL != host_instance(sek->host, ref)) {
|
|
555
|
+
ref = host_autotag(sek->host, kind);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
memset(&declared, 0, sizeof(declared));
|
|
559
|
+
declared.options = sek_optionsof(spec);
|
|
560
|
+
|
|
561
|
+
/* `load` runs the definition's `define`, which builds the provider from
|
|
562
|
+
* the spec; `activate` takes the instance live. Nothing is contacted by
|
|
563
|
+
* either: a provider opens nothing until its first lookup. */
|
|
564
|
+
host_load(sek->host, ref, &declared);
|
|
565
|
+
host_activate(sek->host, ref);
|
|
566
|
+
|
|
567
|
+
exported = host_exports(sek->host, sek_fmt(sek->pool, "%s/%s", ref, SEK_PROVIDER_EXPORT));
|
|
568
|
+
provider = visnum(exported) ? sek_build_at(vasnum(exported)) : NULL;
|
|
569
|
+
|
|
570
|
+
if (NULL == provider) {
|
|
571
|
+
return sek_fmt(sek->pool, "sekreto: plugin %s exported no provider", kind);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
out->store = sek_strdup(sek->pool, store);
|
|
575
|
+
out->ref = sek_strdup(sek->pool, ref);
|
|
576
|
+
out->provider = provider;
|
|
577
|
+
|
|
578
|
+
return NULL;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/* The whole of construction, inside the caller's catch frame. */
|
|
582
|
+
static sek_err build(sek_sekreto *sek, const sek_options *options) {
|
|
583
|
+
Definition **builtins;
|
|
584
|
+
size_t count = sek_builtins(&builtins);
|
|
585
|
+
size_t index;
|
|
586
|
+
|
|
587
|
+
/* Built-ins first, then the plugins, into one catalog: a plugin that
|
|
588
|
+
* names a built-in kind replaces it, which is how a host substitutes an
|
|
589
|
+
* implementation and never an accident, because the four names are
|
|
590
|
+
* documented. */
|
|
591
|
+
for (index = 0; index < count; index++) {
|
|
592
|
+
catalog_add(sek->catalog, builtins[index]);
|
|
593
|
+
}
|
|
594
|
+
for (index = 0; index < options->plugincount; index++) {
|
|
595
|
+
catalog_add(sek->catalog, options->plugins[index]);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
for (index = 0; index < options->count; index++) {
|
|
599
|
+
const sek_spec *spec = &options->providers[index];
|
|
600
|
+
sek_err err;
|
|
601
|
+
|
|
602
|
+
/* A provider already built joins the chain as it is, under its own
|
|
603
|
+
* store name, backed by no instance. */
|
|
604
|
+
if (NULL != spec->provider) {
|
|
605
|
+
sek->entries[sek->count].provider = spec->provider;
|
|
606
|
+
sek->entries[sek->count].ref = "";
|
|
607
|
+
sek->entries[sek->count].store = sek_empty(spec->name)
|
|
608
|
+
? sek_storename(sek->pool, spec->provider)
|
|
609
|
+
: sek_strdup(sek->pool, spec->name);
|
|
610
|
+
sek->count++;
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
err = declare(sek, spec, &sek->entries[sek->count]);
|
|
615
|
+
if (NULL != err) {
|
|
616
|
+
return err;
|
|
617
|
+
}
|
|
618
|
+
sek->count++;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
return NULL;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/* Construction, inside the one catch frame the whole of it runs under.
|
|
625
|
+
*
|
|
626
|
+
* Its own function so that nothing a `longjmp` comes back through is a
|
|
627
|
+
* parameter this code then modifies: `options` and `sek` are read-only
|
|
628
|
+
* here, and only `failure` straddles the frame. -Wclobbered is on, and it
|
|
629
|
+
* is the warning that catches exactly this. */
|
|
630
|
+
static sek_err construct(sek_pool *pool, const sek_options *options, sek_sekreto *sek) {
|
|
631
|
+
CatchFrame frame;
|
|
632
|
+
/* volatile because it is written inside the frame and read after a
|
|
633
|
+
* longjmp has come back through it. C guarantees nothing else about a
|
|
634
|
+
* local a setjmp handler reads. */
|
|
635
|
+
volatile sek_err failure = NULL;
|
|
636
|
+
|
|
637
|
+
/* The pool reaches each kind's `define` through here, and the providers
|
|
638
|
+
* come back the same way. Held for exactly this call. */
|
|
639
|
+
sek_build_begin(pool);
|
|
640
|
+
|
|
641
|
+
if (0 == PLUGIN_TRY(&frame)) {
|
|
642
|
+
HostOptions hostopts;
|
|
643
|
+
memset(&hostopts, 0, sizeof(hostopts));
|
|
644
|
+
hostopts.catalog = sek->catalog;
|
|
645
|
+
sek->host = makehost(&hostopts);
|
|
646
|
+
|
|
647
|
+
failure = build(sek, options);
|
|
648
|
+
PLUGIN_END(&frame);
|
|
649
|
+
} else {
|
|
650
|
+
failure = unwrap(pool, plugin_caught());
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
sek_build_end();
|
|
654
|
+
|
|
655
|
+
return failure;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
sek_err sek_new(sek_pool *pool, const sek_options *options, sek_sekreto **out) {
|
|
659
|
+
sek_sekreto *sek = (sek_sekreto *)sek_alloc(pool, sizeof(sek_sekreto));
|
|
660
|
+
sek_options empty;
|
|
661
|
+
sek_err failure;
|
|
662
|
+
|
|
663
|
+
memset(&empty, 0, sizeof(empty));
|
|
664
|
+
|
|
665
|
+
sek->pool = pool;
|
|
666
|
+
sek->catalog = makecatalog();
|
|
667
|
+
sek->host = NULL;
|
|
668
|
+
sek->count = 0;
|
|
669
|
+
sek->docache = NULL == options || 0 == options->nocache;
|
|
670
|
+
sek->entries = (entry *)sek_alloc(
|
|
671
|
+
pool, (NULL == options || 0 == options->count ? 1 : options->count) * sizeof(entry));
|
|
672
|
+
sek->cachecap = 8;
|
|
673
|
+
sek->cache = (cached *)sek_alloc(pool, sek->cachecap * sizeof(cached));
|
|
674
|
+
sek->cachelen = 0;
|
|
675
|
+
sek->seen = sek_list_new(pool);
|
|
676
|
+
|
|
677
|
+
failure = construct(pool, NULL == options ? &empty : options, sek);
|
|
678
|
+
if (NULL != failure) {
|
|
679
|
+
return failure;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
*out = sek;
|
|
683
|
+
|
|
684
|
+
return NULL;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
static void remember(sek_sekreto *sek, const char *store, const char *name, const char *value) {
|
|
688
|
+
if (sek->cachelen == sek->cachecap) {
|
|
689
|
+
size_t cap = sek->cachecap * 2;
|
|
690
|
+
cached *bigger = (cached *)sek_alloc(sek->pool, cap * sizeof(cached));
|
|
691
|
+
memcpy(bigger, sek->cache, sek->cachelen * sizeof(cached));
|
|
692
|
+
sek->cache = bigger;
|
|
693
|
+
sek->cachecap = cap;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
sek->cache[sek->cachelen].store = sek_strdup(sek->pool, store);
|
|
697
|
+
sek->cache[sek->cachelen].name = sek_strdup(sek->pool, name);
|
|
698
|
+
sek->cache[sek->cachelen].value = sek_strdup(sek->pool, value);
|
|
699
|
+
sek->cachelen++;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/* The one path both readers share. `store` is "" for a transparent read,
|
|
703
|
+
* so a directed read and a transparent one never alias in the cache.
|
|
704
|
+
*
|
|
705
|
+
* `only` is NULL for a transparent read and the store name for a directed
|
|
706
|
+
* one, rather than a pre-filtered array of entries: filtering inline
|
|
707
|
+
* keeps the walk allocation-free, and in an arena a per-call allocation
|
|
708
|
+
* is never handed back. */
|
|
709
|
+
static sek_err resolve(sek_sekreto *sek, const char *store, const char *only, const char *name,
|
|
710
|
+
char **out) {
|
|
711
|
+
size_t index;
|
|
712
|
+
sek_err err;
|
|
713
|
+
|
|
714
|
+
*out = NULL;
|
|
715
|
+
|
|
716
|
+
/* The name is validated FIRST: before the cache, and before the first
|
|
717
|
+
* provider is asked. */
|
|
718
|
+
err = sek_checkname(sek->pool, name);
|
|
719
|
+
if (NULL != err) {
|
|
720
|
+
return err;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
if (sek->docache) {
|
|
724
|
+
for (index = 0; index < sek->cachelen; index++) {
|
|
725
|
+
if (0 == strcmp(sek->cache[index].store, store) &&
|
|
726
|
+
0 == strcmp(sek->cache[index].name, name)) {
|
|
727
|
+
/* A cache hit does not push to `seen`: it is already there. */
|
|
728
|
+
*out = sek->cache[index].value;
|
|
729
|
+
return NULL;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
for (index = 0; index < sek->count; index++) {
|
|
735
|
+
char *found = NULL;
|
|
736
|
+
|
|
737
|
+
if (NULL != only && 0 != strcmp(sek->entries[index].store, only)) {
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/* A provider that raises is not caught: the error propagates out of
|
|
742
|
+
* get/try/getfrom/tryfrom, because a store that could not answer must
|
|
743
|
+
* not be mistaken for one that answered "no". */
|
|
744
|
+
err = sek->entries[index].provider->lookup(sek->entries[index].provider, name, &found);
|
|
745
|
+
if (NULL != err) {
|
|
746
|
+
return err;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/* THE EMPTY STRING IS A HIT. Only NULL means "ask the next one". */
|
|
750
|
+
if (NULL != found) {
|
|
751
|
+
if (sek->docache) {
|
|
752
|
+
remember(sek, store, name, found);
|
|
753
|
+
}
|
|
754
|
+
sek_list_add(sek->seen, found);
|
|
755
|
+
*out = found;
|
|
756
|
+
return NULL;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/* Misses are never cached. */
|
|
761
|
+
return NULL;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
sek_err sek_try(sek_sekreto *sek, const char *name, char **out) {
|
|
765
|
+
return resolve(sek, "", NULL, name, out);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
sek_err sek_get(sek_sekreto *sek, const char *name, char **out) {
|
|
769
|
+
sek_err err = sek_try(sek, name, out);
|
|
770
|
+
|
|
771
|
+
if (NULL != err) {
|
|
772
|
+
return err;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if (NULL == *out) {
|
|
776
|
+
return sek_fmt(sek->pool, "sekreto: unknown secret: %s", name);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
return NULL;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/* Naming a store that is not in the chain is an error, not a miss:
|
|
783
|
+
* `try` already means "this store may not have it", so it cannot also
|
|
784
|
+
* mean "this store may not exist" without hiding a typo. Raised BEFORE
|
|
785
|
+
* the name is validated. */
|
|
786
|
+
sek_err sek_tryfrom(sek_sekreto *sek, const char *store, const char *name, char **out) {
|
|
787
|
+
size_t index;
|
|
788
|
+
int found = 0;
|
|
789
|
+
|
|
790
|
+
*out = NULL;
|
|
791
|
+
|
|
792
|
+
/* Store names may repeat, and a directed read walks every entry that
|
|
793
|
+
* answers to the name, in chain order. */
|
|
794
|
+
for (index = 0; index < sek->count; index++) {
|
|
795
|
+
if (0 == strcmp(sek->entries[index].store, store)) {
|
|
796
|
+
found = 1;
|
|
797
|
+
break;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
if (!found) {
|
|
802
|
+
return sek_fmt(sek->pool, "sekreto: unknown store: %s", store);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
return resolve(sek, store, store, name, out);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
sek_err sek_getfrom(sek_sekreto *sek, const char *store, const char *name, char **out) {
|
|
809
|
+
sek_err err = sek_tryfrom(sek, store, name, out);
|
|
810
|
+
|
|
811
|
+
if (NULL != err) {
|
|
812
|
+
return err;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
if (NULL == *out) {
|
|
816
|
+
return sek_fmt(sek->pool, "sekreto: unknown secret: %s:%s", store, name);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
return NULL;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
sek_err sek_has(sek_sekreto *sek, const char *name, int *out) {
|
|
823
|
+
char *value = NULL;
|
|
824
|
+
sek_err err = sek_try(sek, name, &value);
|
|
825
|
+
|
|
826
|
+
*out = NULL != value;
|
|
827
|
+
|
|
828
|
+
return err;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
sek_err sek_hasin(sek_sekreto *sek, const char *store, const char *name, int *out) {
|
|
832
|
+
char *value = NULL;
|
|
833
|
+
sek_err err = sek_tryfrom(sek, store, name, &value);
|
|
834
|
+
|
|
835
|
+
*out = NULL != value;
|
|
836
|
+
|
|
837
|
+
return err;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
sek_err sek_all(sek_sekreto *sek, const char **names, size_t count, sek_map **out) {
|
|
841
|
+
sek_map *found = sek_map_new(sek->pool);
|
|
842
|
+
size_t index;
|
|
843
|
+
|
|
844
|
+
for (index = 0; index < count; index++) {
|
|
845
|
+
char *value = NULL;
|
|
846
|
+
sek_err err = sek_get(sek, names[index], &value);
|
|
847
|
+
if (NULL != err) {
|
|
848
|
+
return err;
|
|
849
|
+
}
|
|
850
|
+
sek_map_set(found, names[index], value);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
*out = found;
|
|
854
|
+
|
|
855
|
+
return NULL;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
sek_list *sek_sources(sek_sekreto *sek) {
|
|
859
|
+
sek_list *out = sek_list_new(sek->pool);
|
|
860
|
+
size_t index;
|
|
861
|
+
|
|
862
|
+
for (index = 0; index < sek->count; index++) {
|
|
863
|
+
sek_provider *provider = sek->entries[index].provider;
|
|
864
|
+
sek_list_add(out, provider->describe(provider));
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
return out;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
sek_list *sek_stores(sek_sekreto *sek) {
|
|
871
|
+
sek_list *out = sek_list_new(sek->pool);
|
|
872
|
+
size_t index;
|
|
873
|
+
|
|
874
|
+
for (index = 0; index < sek->count; index++) {
|
|
875
|
+
size_t seen;
|
|
876
|
+
int already = 0;
|
|
877
|
+
|
|
878
|
+
for (seen = 0; seen < out->len; seen++) {
|
|
879
|
+
if (0 == strcmp(out->items[seen], sek->entries[index].store)) {
|
|
880
|
+
already = 1;
|
|
881
|
+
break;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
if (!already) {
|
|
886
|
+
sek_list_add(out, sek->entries[index].store);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
return out;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
char *sek_redact_text(sek_sekreto *sek, const char *text) {
|
|
894
|
+
return sek_redact(sek->pool, text, sek->seen);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
void sek_refresh(sek_sekreto *sek) { sek->cachelen = 0; }
|
|
898
|
+
|
|
899
|
+
/* Every plugin instance is deactivated and unloaded, in reverse, which is
|
|
900
|
+
* voxgig/plugin's teardown and not sekreto's: a provider that acquired a
|
|
901
|
+
* resource at activation has it released here, by the instance scope.
|
|
902
|
+
*
|
|
903
|
+
* The chain and the cache go with them; `seen` stays, so redaction still
|
|
904
|
+
* knows every value this Sekreto ever resolved. */
|
|
905
|
+
sek_err sek_close(sek_sekreto *sek) {
|
|
906
|
+
CatchFrame frame;
|
|
907
|
+
volatile sek_err failure = NULL;
|
|
908
|
+
|
|
909
|
+
if (0 == PLUGIN_TRY(&frame)) {
|
|
910
|
+
host_close(sek->host);
|
|
911
|
+
PLUGIN_END(&frame);
|
|
912
|
+
} else {
|
|
913
|
+
failure = unwrap(sek->pool, plugin_caught());
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
sek->count = 0;
|
|
917
|
+
sek->cachelen = 0;
|
|
918
|
+
|
|
919
|
+
return failure;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/* `cache` and `seen` are ordinary fields, so the obvious debug print of a
|
|
923
|
+
* Sekreto would emit every resolved secret. This one cannot reach a
|
|
924
|
+
* value. The spacing is literal: an empty chain yields
|
|
925
|
+
* `Sekreto { stores: [ ] }`. */
|
|
926
|
+
char *sek_show(sek_sekreto *sek) {
|
|
927
|
+
sek_list *stores = sek_stores(sek);
|
|
928
|
+
sek_buf out;
|
|
929
|
+
size_t index;
|
|
930
|
+
|
|
931
|
+
sek_buf_init(&out, sek->pool);
|
|
932
|
+
sek_buf_add(&out, "Sekreto { stores: [ ");
|
|
933
|
+
|
|
934
|
+
for (index = 0; index < stores->len; index++) {
|
|
935
|
+
if (0 < index) {
|
|
936
|
+
sek_buf_add(&out, ", ");
|
|
937
|
+
}
|
|
938
|
+
sek_buf_add(&out, stores->items[index]);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
sek_buf_add(&out, " ] }");
|
|
942
|
+
|
|
943
|
+
return out.data;
|
|
944
|
+
}
|