mod common;
use common::run_lua;
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
#[tokio::test]
async fn test_require_vault() {
let script = r#"
local vault = require("assay.vault")
assert.not_nil(vault)
assert.not_nil(vault.client)
"#;
run_lua(script).await.unwrap();
}
#[tokio::test]
async fn test_vault_read() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secret/data/mykey"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {"data": {"username": "admin", "password": "secret123"}}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local data = c:read("secret/data/mykey")
assert.eq(data.data.username, "admin")
assert.eq(data.data.password, "secret123")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_read_404() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secret/data/missing"))
.respond_with(ResponseTemplate::new(404))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local data = c:read("secret/data/missing")
assert.eq(data, nil)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_write() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/secret/data/newkey"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c:write("secret/data/newkey", {{ data = {{ key = "value" }} }})
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_delete() {
let server = MockServer::start().await;
Mock::given(method("DELETE"))
.and(path("/v1/secret/data/oldkey"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c:delete("secret/data/oldkey")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secret/metadata"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {"keys": ["key1", "key2", "key3"]}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local keys = c:list("secret/metadata")
assert.eq(#keys, 3)
assert.eq(keys[1], "key1")
assert.eq(keys[3], "key3")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_list_empty() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secret/metadata"))
.respond_with(ResponseTemplate::new(404))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local keys = c:list("secret/metadata")
assert.eq(#keys, 0)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_kv_get() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secret/data/mykey"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {"data": {"foo": "bar"}}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local data = c.kv:get("secret", "mykey")
assert.eq(data.data.foo, "bar")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_kv_put() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/secret/data/mykey"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.kv:put("secret", "mykey", {{ username = "admin", password = "s3cret" }})
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_kv_delete() {
let server = MockServer::start().await;
Mock::given(method("DELETE"))
.and(path("/v1/secret/data/mykey"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.kv:delete("secret", "mykey")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_kv_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secret/metadata/"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {"keys": ["db-creds", "api-keys", "tls/"]}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local keys = c.kv:list("secret")
assert.eq(#keys, 3)
assert.eq(keys[1], "db-creds")
assert.eq(keys[3], "tls/")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_kv_metadata() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secret/metadata/mykey"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {
"created_time": "2026-01-15T10:30:00Z",
"current_version": 3,
"max_versions": 10,
"oldest_version": 1,
"versions": {
"1": {"created_time": "2026-01-10T08:00:00Z", "deletion_time": ""},
"2": {"created_time": "2026-01-12T09:00:00Z", "deletion_time": ""},
"3": {"created_time": "2026-01-15T10:30:00Z", "deletion_time": ""}
}
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local meta = c.kv:metadata("secret", "mykey")
assert.eq(meta.data.current_version, 3)
assert.eq(meta.data.max_versions, 10)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_health() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/sys/health"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"initialized": true,
"sealed": false,
"standby": false,
"performance_standby": false,
"replication_performance_mode": "disabled",
"replication_dr_mode": "disabled",
"server_time_utc": 1700000000,
"version": "1.15.0",
"cluster_name": "vault-cluster-abc123",
"cluster_id": "550e8400-e29b-41d4-a716-446655440000"
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local h = c.sys:health()
assert.eq(h.initialized, true)
assert.eq(h.sealed, false)
assert.eq(h.version, "1.15.0")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_seal_status() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/sys/seal-status"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"type": "shamir",
"initialized": true,
"sealed": false,
"t": 3,
"n": 5,
"progress": 0,
"nonce": "",
"version": "1.15.0",
"build_date": "2026-01-01T00:00:00Z",
"migration": false,
"cluster_name": "vault-cluster-abc123",
"cluster_id": "550e8400-e29b-41d4-a716-446655440000",
"recovery_seal": false,
"storage_type": "raft"
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local s = c.sys:seal_status()
assert.eq(s.sealed, false)
assert.eq(s.initialized, true)
assert.eq(s.t, 3)
assert.eq(s.n, 5)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_is_sealed() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/sys/seal-status"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"sealed": true,
"initialized": true,
"t": 3,
"n": 5,
"progress": 1
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
assert.eq(c.sys:is_sealed(), true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_is_initialized() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/sys/seal-status"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"sealed": false,
"initialized": true,
"t": 3,
"n": 5,
"progress": 0
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
assert.eq(c.sys:is_initialized(), true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_policy_get() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/sys/policies/acl/my-policy"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {
"name": "my-policy",
"rules": "path \"secret/data/*\" {\n capabilities = [\"read\"]\n}"
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local pol = c.policies:get("my-policy")
assert.eq(pol.name, "my-policy")
assert.contains(pol.rules, "secret/data")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_policy_put() {
let server = MockServer::start().await;
Mock::given(method("PUT"))
.and(path("/v1/sys/policies/acl/my-policy"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.policies:create("my-policy", 'path "secret/data/*" {{ capabilities = ["read"] }}')
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_policy_delete() {
let server = MockServer::start().await;
Mock::given(method("DELETE"))
.and(path("/v1/sys/policies/acl/my-policy"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.policies:delete("my-policy")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_policy_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/sys/policies/acl"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {"keys": ["default", "root", "my-policy"]}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local policies = c.policies:list()
assert.eq(#policies, 3)
assert.eq(policies[1], "default")
assert.eq(policies[3], "my-policy")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_auth_enable() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/sys/auth/kubernetes"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.auth:enable("kubernetes", "kubernetes", {{ description = "K8s auth" }})
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_auth_disable() {
let server = MockServer::start().await;
Mock::given(method("DELETE"))
.and(path("/v1/sys/auth/kubernetes"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.auth:disable("kubernetes")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_auth_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/sys/auth"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {
"token/": {
"type": "token",
"description": "token based credentials"
},
"kubernetes/": {
"type": "kubernetes",
"description": "K8s auth"
}
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local auths = c.auth:methods()
assert.not_nil(auths["token/"])
assert.eq(auths["token/"].type, "token")
assert.eq(auths["kubernetes/"].type, "kubernetes")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_auth_config() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/auth/kubernetes/config"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.auth:config("kubernetes", {{
kubernetes_host = "https://kubernetes.default.svc",
}})
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_auth_create_role() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/auth/kubernetes/role/my-app"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.auth:create_role("kubernetes", "my-app", {{
bound_service_account_names = {{ "my-app" }},
bound_service_account_namespaces = {{ "default" }},
policies = {{ "my-policy" }},
ttl = "1h",
}})
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_auth_read_role() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/auth/kubernetes/role/my-app"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {
"bound_service_account_names": ["my-app"],
"bound_service_account_namespaces": ["default"],
"policies": ["my-policy"],
"ttl": 3600,
"max_ttl": 86400
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local role = c.auth:get_role("kubernetes", "my-app")
assert.eq(role.policies[1], "my-policy")
assert.eq(role.ttl, 3600)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_auth_list_roles() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/auth/kubernetes/role"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {"keys": ["my-app", "worker", "admin"]}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local roles = c.auth:list_roles("kubernetes")
assert.eq(#roles, 3)
assert.eq(roles[1], "my-app")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_engine_enable() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/sys/mounts/transit"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.engines:enable("transit", "transit", {{ description = "Encryption as a service" }})
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_engine_disable() {
let server = MockServer::start().await;
Mock::given(method("DELETE"))
.and(path("/v1/sys/mounts/transit"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.engines:disable("transit")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_engine_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/sys/mounts"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {
"secret/": {
"type": "kv",
"options": {"version": "2"}
},
"transit/": {
"type": "transit",
"description": "Encryption as a service"
},
"pki/": {
"type": "pki",
"description": "PKI engine"
}
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local engines = c.engines:list()
assert.not_nil(engines["secret/"])
assert.eq(engines["secret/"].type, "kv")
assert.eq(engines["transit/"].type, "transit")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_engine_tune() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/sys/mounts/secret/tune"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.engines:tune("secret", {{ max_lease_ttl = "87600h", default_lease_ttl = "1h" }})
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_token_create() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/auth/token/create"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"auth": {
"client_token": "hvs.CAESI_new_child_token",
"accessor": "accessor-abc123",
"policies": ["default", "my-policy"],
"token_policies": ["default", "my-policy"],
"metadata": {},
"lease_duration": 3600,
"renewable": true
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local auth = c.token:create({{ policies = {{ "my-policy" }}, ttl = "1h" }})
assert.eq(auth.client_token, "hvs.CAESI_new_child_token")
assert.eq(auth.renewable, true)
assert.eq(auth.lease_duration, 3600)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_token_lookup() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/auth/token/lookup"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {
"accessor": "accessor-abc123",
"creation_time": 1700000000,
"creation_ttl": 3600,
"display_name": "token",
"expire_time": "2026-02-10T12:00:00Z",
"id": "hvs.CAESI_some_token",
"policies": ["default", "my-policy"],
"renewable": true,
"ttl": 1800
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local info = c.token:lookup("hvs.CAESI_some_token")
assert.eq(info.id, "hvs.CAESI_some_token")
assert.eq(info.policies[2], "my-policy")
assert.eq(info.renewable, true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_token_lookup_self() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/auth/token/lookup-self"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {
"accessor": "accessor-self-123",
"creation_time": 1700000000,
"id": "hvs.CAESI_self_token",
"policies": ["default", "admin"],
"ttl": 7200
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local info = c.token:lookup_self()
assert.eq(info.id, "hvs.CAESI_self_token")
assert.eq(info.policies[2], "admin")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_token_revoke() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/auth/token/revoke"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.token:revoke("hvs.CAESI_revoke_me")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_token_revoke_self() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/auth/token/revoke-self"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.token:revoke_self()
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_transit_encrypt() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/transit/encrypt/my-key"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {
"ciphertext": "vault:v1:ABCDEF1234567890encrypted"
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local ct = c.transit:encrypt("my-key", "hello world")
assert.eq(ct, "vault:v1:ABCDEF1234567890encrypted")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_transit_decrypt() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/transit/decrypt/my-key"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {
"plaintext": "aGVsbG8gd29ybGQ="
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local pt = c.transit:decrypt("my-key", "vault:v1:ABCDEF1234567890encrypted")
assert.eq(pt, "hello world")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_transit_create_key() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/transit/keys/new-key"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.transit:create_key("new-key", {{ type = "aes256-gcm96" }})
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_transit_list_keys() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/transit/keys"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {"keys": ["my-key", "backup-key", "signing-key"]}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local keys = c.transit:list_keys()
assert.eq(#keys, 3)
assert.eq(keys[1], "my-key")
assert.eq(keys[3], "signing-key")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_pki_issue() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/pki/issue/web-certs"))
.respond_with(
ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {
"certificate": "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----",
"issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----",
"private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIE...\n-----END RSA PRIVATE KEY-----",
"private_key_type": "rsa",
"serial_number": "39:dd:2e:90:b7:23:1f:8d:d3:7d:31:c5"
}
})),
)
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local cert = c.pki:issue("pki", "web-certs", {{ common_name = "example.com", ttl = "720h" }})
assert.contains(cert.certificate, "BEGIN CERTIFICATE")
assert.contains(cert.private_key, "BEGIN RSA PRIVATE KEY")
assert.eq(cert.private_key_type, "rsa")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_pki_ca_cert() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/pki/ca/pem"))
.respond_with(
ResponseTemplate::new(200).set_body_string(
"-----BEGIN CERTIFICATE-----\nMIICpDCCAYwCCQC7fC0bJNvDPDANBgkqhkiG9w0BAQsFADAU\n-----END CERTIFICATE-----\n",
),
)
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local pem = c.pki:ca_cert("pki")
assert.contains(pem, "BEGIN CERTIFICATE")
assert.contains(pem, "END CERTIFICATE")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_pki_create_role() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/pki/roles/web-certs"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
c.pki:create_role("pki", "web-certs", {{
allowed_domains = {{ "example.com" }},
allow_subdomains = true,
max_ttl = "720h",
}})
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_wait_success() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/sys/health"))
.respond_with(
ResponseTemplate::new(200).set_body_json(serde_json::json!({"initialized": true})),
)
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local result = vault.wait("{}", {{ timeout = 5, interval = 0.1 }})
assert.eq(result, true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_wait_timeout() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/sys/health"))
.respond_with(ResponseTemplate::new(503))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
vault.wait("{}", {{ timeout = 1, interval = 0.5 }})
"#,
server.uri()
);
let result = run_lua(&script).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_vault_ensure_credentials_existing() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secrets/data/db/postgres"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {"data": {"username": "admin", "password": "existing_secret"}}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local generator_called = false
local function generator()
generator_called = true
return {{ password = "new_secret" }}
end
local data = vault.ensure_credentials(c, "db/postgres", "password", generator)
assert.eq(data.username, "admin")
assert.eq(data.password, "existing_secret")
assert.eq(generator_called, false)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_ensure_credentials_new() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secrets/data/db/new"))
.respond_with(ResponseTemplate::new(404))
.mount(&server)
.await;
Mock::given(method("POST"))
.and(path("/v1/secrets/data/db/new"))
.respond_with(ResponseTemplate::new(204))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local generator_called = false
local function generator()
generator_called = true
return {{ password = "generated_secret" }}
end
local data = vault.ensure_credentials(c, "db/new", "password", generator)
assert.eq(data.password, "generated_secret")
assert.eq(generator_called, true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_assert_secret_success() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secrets/data/db/postgres"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {"data": {"username": "admin", "password": "secret123"}}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
local data = vault.assert_secret(c, "db/postgres", {{"username", "password"}})
assert.eq(data.username, "admin")
assert.eq(data.password, "secret123")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_vault_assert_secret_missing() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secrets/data/db/missing"))
.respond_with(ResponseTemplate::new(404))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
vault.assert_secret(c, "db/missing", {{"username"}})
"#,
server.uri()
);
let result = run_lua(&script).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_vault_assert_secret_missing_key() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/secrets/data/db/partial"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": {"data": {"username": "admin"}}
})))
.mount(&server)
.await;
let script = format!(
r#"
local vault = require("assay.vault")
local c = vault.client("{}", "test-token")
vault.assert_secret(c, "db/partial", {{"username", "missing_key"}})
"#,
server.uri()
);
let result = run_lua(&script).await;
assert!(result.is_err());
}