Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vault secret resolver module #13

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,11 @@ libtestisolator_la_LDFLAGS = \
pkglib_LTLIBRARIES += libtesthook.la
libtesthook_la_SOURCES = hook/test_hook_module.cpp
libtesthook_la_LDFLAGS = -release $(PACKAGE_VERSION) -shared $(MESOS_LDFLAGS)

# Library containing vault secretresolver module.
pkglib_LTLIBRARIES += libvaultsecretsresolver.la
libvaultsecretsresolver_la_SOURCES = \
secretresolver/vault_secret_resolver_module.cpp \
secretresolver/HttpClient.cpp \
secretresolver/VaultClient.cpp
libvaultsecretsresolver_la_LDFLAGS = -release $(PACKAGE_VERSION) -shared $(MESOS_LDFLAGS)
5 changes: 4 additions & 1 deletion isolator/test_isolator_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* limitations under the License.
*/

#include <string>

#include <mesos/mesos.hpp>

#include <mesos/module/isolator.hpp>
Expand Down Expand Up @@ -108,7 +110,8 @@ process::Future<ContainerLimitation> TestIsolatorProcess::watch(

process::Future<Nothing> TestIsolatorProcess::update(
const ContainerID& containerId,
const Resources& resources)
const Resources& resourceRequests,
const google::protobuf::Map<std::string, Value::Scalar>& resourceLimits = {})
{
if (!promises.contains(containerId)) {
return process::Failure("Unknown container: " + stringify(containerId));
Expand Down
12 changes: 9 additions & 3 deletions isolator/test_isolator_module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#ifndef __TEST_ISOLATOR_MODULE_HPP__
#define __TEST_ISOLATOR_MODULE_HPP__

#include <string>

#include <mesos/mesos.hpp>

#include <mesos/slave/isolator.hpp>
Expand Down Expand Up @@ -61,7 +63,8 @@ class TestIsolatorProcess : public process::Process<TestIsolatorProcess>

process::Future<Nothing> update(
const ContainerID& containerId,
const Resources& resources);
const Resources& resourceRequests,
const google::protobuf::Map<std::string, Value::Scalar>& resourceLimits);

process::Future<ResourceStatistics> usage(
const ContainerID& containerId);
Expand Down Expand Up @@ -150,12 +153,15 @@ class TestIsolator : public mesos::slave::Isolator

virtual process::Future<Nothing> update(
const ContainerID& containerId,
const Resources& resources) override
const Resources& resourceRequests,
const google::protobuf::Map<
std::string, Value::Scalar>& resourceLimits = {}) override
{
return dispatch(process.get(),
&TestIsolatorProcess::update,
containerId,
resources);
resourceRequests,
resourceLimits);
}

virtual process::Future<ResourceStatistics> usage(
Expand Down
Binary file added secretresolver/.VaultClient.cpp.swp
Binary file not shown.
Binary file added secretresolver/.VaultClient.h.swp
Binary file not shown.
Binary file not shown.
97 changes: 97 additions & 0 deletions secretresolver/HttpClient.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include <curl/curl.h>
#include <iostream>

#include "HttpClient.h"

static size_t writeCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((std::string *) userp)->append((char *) contents, size * nmemb);
return size * nmemb;
}

HttpClient::HttpClient() : HttpClient(false) {}

HttpClient::HttpClient(bool debug) {
this->debug = debug;
}

void HttpClient::setCacert(std::string cacert) {
this->cacert = cacert;
}

std::string HttpClient::get(std::string url, std::string token) {

CURL *curl;
std::string readBuffer;

curl = curl_easy_init();
if (curl) {
struct curl_slist *chunk = nullptr;
chunk = curl_slist_append(chunk, ("X-Vault-Token: " + token).c_str());

// TODO: SSL verify host and peer
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_CAINFO, cacert.c_str());

if (debug) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
}

CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cout << "GET " << url << " failed: " << curl_easy_strerror(res) << std::endl;
}

curl_easy_cleanup(curl);
curl_slist_free_all(chunk);
}

return readBuffer;
}

std::string HttpClient::post(std::string url, std::string token) {
return post(url,token,"");
}

std::string HttpClient::post(std::string url, std::string token, std::string value) {

CURL *curl;
CURLcode res = CURLE_SEND_ERROR;
std::string readBuffer;

curl = curl_easy_init();
if (curl) {
struct curl_slist *chunk = nullptr;
if(!token.empty()) {
chunk = curl_slist_append(chunk, ("X-Vault-Token: " + token).c_str());
}
chunk = curl_slist_append(chunk, "Accept: application/json");
chunk = curl_slist_append(chunk, "Content-Type: application/json");

// TODO: SSL verify host and peer
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, value.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_CAINFO, cacert.c_str());

if (debug) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
}

res = curl_easy_perform(curl);

if (res != CURLE_OK) {
std::cout << "POST " << url << " failed: " << curl_easy_strerror(res) << std::endl;
}

curl_easy_cleanup(curl);
curl_slist_free_all(chunk);
}

return readBuffer;
}
17 changes: 17 additions & 0 deletions secretresolver/HttpClient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef LIBVAULT_HTTPCLIENT_H
#define LIBVAULT_HTTPCLIENT_H

class HttpClient {
private:
std::string cacert;
bool debug;
public:
HttpClient();
HttpClient(bool debug);
std::string get(std::string url, std::string string);
std::string post(std::string url, std::string token);
std::string post(std::string url, std::string token, std::string value);
void setCacert(std::string cacert);
};

#endif //LIBVAULT_HTTPCLIENT_H
88 changes: 88 additions & 0 deletions secretresolver/VaultClient.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include <string>
#include <iostream>
#include <chrono>
#include <thread>

#include "VaultClient.h"
#include "HttpClient.h"
#include "json.hpp"
#include <process/process.hpp>
using process::Failure;

using json = nlohmann::json;

VaultClient::VaultClient(std::string addr, std::string prefix, std::string token, std::string cacert) : VaultClient(addr, prefix, token, cacert, false){}

VaultClient::VaultClient(std::string addr, std::string prefix, std::string token, std::string cacert, bool debug) {
this->addr = addr;
this->token = token;
this->prefix = prefix;
this->httpClient = HttpClient(debug);
this->httpClient.setCacert(cacert);
}

VaultClient::VaultClient(std::string addr, std::string prefix, std::string role, std::string secret, int refreshDelaySeconds, std::string cacert) : VaultClient(addr, prefix, role, secret, refreshDelaySeconds, cacert, false){}

VaultClient::VaultClient(std::string addr, std::string prefix, std::string role, std::string secret, int refreshDelaySeconds, std::string cacert, bool debug) {
VLOG(2) << "VaultClient init by role " + role ;
this->addr = addr;
this->role = role;
this->secret = secret;
this->refreshDelaySeconds = refreshDelaySeconds;
this->prefix = prefix;
this->httpClient = HttpClient(debug);
this->httpClient.setCacert(cacert);
}

std::string VaultClient::vaultUrl(std::string path) {
return addr + "/v1/" + prefix + path;
}

void autoRenewToken(HttpClient httpClient,std::string addr, std::string token, int delaySeconds){
while(true) {
std::this_thread::sleep_for(std::chrono::seconds(delaySeconds));
httpClient.post(addr + "/v1/auth/token/renew-self", token);
}
}

std::string VaultClient::getToken() {
if(token.empty()) {
std::string b = "{\"role_id\":\"" + role + "\",\"secret_id\":\"" + secret + "\"}";
VLOG(2) << "login body " + b;
std::string res = httpClient.post(addr + "/v1/auth/approle/login", "", b);
VLOG(2) << "login result " + res;
json j = json::parse(res);
if(j.count("auth") == 0) {
return "";
}
token = j["auth"]["client_token"];
if ( ! token.empty()) {
std::thread t(autoRenewToken, httpClient, addr, token, refreshDelaySeconds);
t.detach();
}

}
return token;
}

std::string VaultClient::get(std::string path) {
std::string t = getToken();
VLOG(2) << "token " + t;
if(t.empty()) {
return "";
}
return httpClient.get(vaultUrl(path), t);
}

std::string VaultClient::put(std::string path, std::unordered_map<std::string, std::string> map) {
json j;
j["data"] = json::object();
std::for_each(map.begin(), map.end(), [&](std::pair<std::string, std::string> pair) {
j["data"][pair.first] = pair.second;
});

return httpClient.post(vaultUrl(path), getToken(), j.dump());
}



30 changes: 30 additions & 0 deletions secretresolver/VaultClient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef LIBVAULT_VAULTCLIENT_H
#define LIBVAULT_VAULTCLIENT_H

#include <unordered_map>
#include "HttpClient.h"

void autoRenewToken(HttpClient httpClient, std::string addr, std::string token, int delaySeconds);

class VaultClient {
private:
std::string addr;
std::string token;
std::string role;
std::string secret;
int refreshDelaySeconds;
std::string prefix;
bool debug;
HttpClient httpClient = (bool)nullptr;
std::string vaultUrl(std::string path);
std::string getToken();
public:
VaultClient(std::string addr, std::string prefix, std::string token, std::string cacert);
VaultClient(std::string addr, std::string prefix, std::string token, std::string cacert, bool debug);
VaultClient(std::string addr, std::string prefix, std::string role, std::string secret, int refreshDelaySeconds, std::string cacert);
VaultClient(std::string addr, std::string prefix, std::string role, std::string secret, int refreshDelaySeconds, std::string cacert, bool debug);
std::string get(std::string path);
std::string put(std::string path, std::unordered_map<std::string, std::string> map);
};

#endif //LIBVAULT_VAULTCLIENT_H
Loading