diff --git a/src/auth/VaultAppRoleAuth.js b/src/auth/VaultAppRoleAuth.js index 00fc781..d9cf277 100644 --- a/src/auth/VaultAppRoleAuth.js +++ b/src/auth/VaultAppRoleAuth.js @@ -16,6 +16,7 @@ class VaultAppRoleAuth extends VaultBaseAuth { this.__roleId = config.role_id; this.__secretId = config.secret_id; + this.__namespace = config.namespace; } _authenticate() { @@ -23,10 +24,16 @@ class VaultAppRoleAuth extends VaultBaseAuth { 'making authentication request: role_id=%s', this.__roleId ); + + const headers = {}; + if (this.__namespace) { + headers['X-Vault-Namespace'] = this.__namespace; + } + return this.__apiClient.makeRequest('POST', `/auth/${this._mount}/login`, { role_id: this.__roleId, secret_id: this.__secretId, - }).then(res => { + }, headers).then(res => { this._log.debug( 'receive token: %s', res.auth.client_token diff --git a/test/auth.appRole.test.js b/test/auth.appRole.test.js new file mode 100644 index 0000000..7d9bd85 --- /dev/null +++ b/test/auth.appRole.test.js @@ -0,0 +1,91 @@ +"use strict"; + +require("co-mocha"); + +const _ = require("lodash"); +const sinon = require("sinon"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(require("sinon-chai")); + +const VaultApiClient = require("../src/VaultApiClient"); +const VaultAppRoleAuth = require("../src/auth/VaultAppRoleAuth"); +const errors = require("../src/errors"); + +const logger = _.fromPairs( + _.map(["error", "warn", "info", "debug", "trace"], (prop) => [prop, _.noop]), +); + +describe("AppRole auth backend", function () { + /** + * @returns {VaultApiClient} + */ + function getApiStub() { + return sinon.createStubInstance(VaultApiClient); + } + + describe("Vault Request", function () { + const mount = "approle"; + + it("Should make a correct vault login request with namespace", async () => { + const api = getApiStub(); + + const auth = new VaultAppRoleAuth( + api, + logger, + { + role_id: "role123", + secret_id: "secret456", + namespace: "ns1", + }, + mount, + ); + + api.makeRequest + .withArgs("POST") + .resolves({ auth: { client_token: "fake_token" } }); + sinon.stub(auth, "_getTokenEntity"); + + await auth._authenticate(); + + expect( + api.makeRequest.calledWith( + "POST", + "/auth/approle/login", + { role_id: "role123", secret_id: "secret456" }, + { "X-Vault-Namespace": "ns1" }, + ), + ).to.be.true; + }); + + it("Should not set namespace header if not provided", async () => { + const api = getApiStub(); + + const auth = new VaultAppRoleAuth( + api, + logger, + { + role_id: "role123", + secret_id: "secret456", + }, + mount, + ); + + api.makeRequest + .withArgs("POST") + .resolves({ auth: { client_token: "fake_token" } }); + sinon.stub(auth, "_getTokenEntity"); + + await auth._authenticate(); + + expect( + api.makeRequest.calledWith( + "POST", + "/auth/approle/login", + { role_id: "role123", secret_id: "secret456" }, + {}, + ), + ).to.be.true; + }); + }); +});