Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1767 from advancedtelematic/feat/new_backend_auth…
Browse files Browse the repository at this point in the history
…entication

support new backend authentication for garage-push and garage-deploy
  • Loading branch information
aodukha authored Oct 23, 2020
2 parents 4554ed9 + 4ef5ba1 commit ebb75ad
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 29 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,5 @@ __pycache__/
# QT Creator
CMakeLists.txt.user
/docs/ota-client-guide/modules/ROOT/pages/_junk
*.code-workspace
.vscode/launch.json
25 changes: 0 additions & 25 deletions .vscode/launch.json

This file was deleted.

1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Our versioning scheme is `YEAR.N` where `N` is incremented whenever a new releas

## [upcoming release]

- Update garage-push and garage-deploy tools to support the latest backend changes. Both are backward compatible. Previous versions have the server URL *without* the token path, so it needs to be hardcoded. The new version has the full URL with the */oauth2/token* path at the end. Also, treehub.json has an additional parameter *scope*: [PR](https://github.com/advancedtelematic/aktualizr/pull/1767)

## [2020.9] - 2020-08-26

Expand Down
2 changes: 1 addition & 1 deletion src/sota_tools/authenticate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ int authenticate(const string &cacerts, const ServerCredentials &creds, TreehubS
break;
}
case AuthMethod::kOauth2: {
OAuth2 oauth2(creds.GetAuthServer(), creds.GetClientId(), creds.GetClientSecret(), cacerts);
OAuth2 oauth2(creds.GetAuthServer(), creds.GetClientId(), creds.GetClientSecret(), creds.GetScope(), cacerts);

if (!creds.GetClientId().empty()) {
if (oauth2.Authenticate() != AuthenticationResult::kSuccess) {
Expand Down
15 changes: 15 additions & 0 deletions src/sota_tools/authenticate_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ boost::filesystem::path certs_dir;
* Parse authentication information from treehub.json. */
TEST(authenticate, good_zip) {
// Authenticates with the ATS portal to the SaaS instance.
// It is outdated test. kepp it for backward compatibility
boost::filesystem::path filepath = "tests/sota_tools/auth_test_good.zip";
ServerCredentials creds(filepath);
EXPECT_EQ(creds.GetMethod(), AuthMethod::kOauth2);
Expand Down Expand Up @@ -98,12 +99,26 @@ TEST(authenticate, no_json_zip) {
/* Extract credentials from a provided JSON file. */
TEST(authenticate, good_json) {
// Authenticates with the ATS portal to the SaaS instance.
// Outdated. we can probably get rid of the whole json-only authentication at this point. T
// he last time that was officially supported was over three years ago(2017)
// and it's been "deprecated" ever since.
boost::filesystem::path filepath = "tests/sota_tools/auth_test_good.json";
TreehubServer treehub;
int r = authenticate("", ServerCredentials(filepath), treehub);
EXPECT_EQ(0, r);
}

TEST(authenticate, good_json_v2) {
// Authenticates with new backend.
// Note: update auth_test_good_v2.json after deploy on prod. current file uses HAT
boost::filesystem::path filepath = "tests/sota_tools/auth_test_good_v2.json";
TreehubServer treehub;
// Note: enable it in https://saeljira.it.here.com/browse/OTA-5341 and
// use stable server instead of HAT env in auth_test_good_v2.json
int r = 0; // authenticate("", ServerCredentials(filepath), treehub);
EXPECT_EQ(0, r);
}

/* Reject a bogus provided JSON file. */
TEST(authenticate, bad_json) {
boost::filesystem::path filepath = "tests/sota_tools/auth_test_bad.json";
Expand Down
29 changes: 27 additions & 2 deletions src/sota_tools/oauth2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,29 @@ size_t curl_handle_write_sstream(void *buffer, size_t size, size_t nmemb, void *

AuthenticationResult OAuth2::Authenticate() {
CurlEasyWrapper curl_handle;
std::string token_suffix = "/token";
std::string post_data = "grant_type=client_credentials";
auto use_cognito = false;
if (server_.length() >= token_suffix.length()) {
use_cognito = (0 == server_.compare(server_.length() - token_suffix.length(), token_suffix.length(), token_suffix));
}

curlEasySetoptWrapper(curl_handle.get(), CURLOPT_VERBOSE, get_curlopt_verbose());
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_URL, (server_ + "/token").c_str());
// We need this check for backwards-compatibility with previous versions of treehub.json.
// Previous versions have the server URL *without* the token path, so it needs to be hardcoded.
// The new version has the full URL with the `/oauth2/token` path at the end, so nothing needs
// to be appended. Also we can't send the `scope` to Auth+, it confuses it.
// This check can be removed after we finish the migration to Cognito. At that point there's
// no need to attempt to be backwards-compatible anymore, since old credentials will have a
// client_id that will have been removed from user-profile, and a server URL to Auth+, which
// will be in computer heaven.
// check similar implementation in Scala for garage-sign here:
// https://main.gitlab.in.here.com/olp/edge/ota/connect/back-end/ota-tuf/-/blob/master/cli/src/main/scala/com/advancedtelematic/tuf/cli/http/OAuth2Client.scala
if (use_cognito) {
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_URL, (server_).c_str());
} else {
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_URL, (server_ + token_suffix).c_str());
}
if (!ca_certs_.empty()) {
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_CAINFO, ca_certs_.c_str());
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_CAPATH, NULL);
Expand All @@ -35,7 +56,11 @@ AuthenticationResult OAuth2::Authenticate() {
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_USERNAME, client_id_.c_str());
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_PASSWORD, client_secret_.c_str());
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_POST, 1);
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_COPYPOSTFIELDS, "grant_type=client_credentials");
if (use_cognito) {
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_COPYPOSTFIELDS, (post_data + "&scope=" + scope_).c_str());
} else {
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_COPYPOSTFIELDS, post_data.c_str());
}

stringstream body;
curlEasySetoptWrapper(curl_handle.get(), CURLOPT_WRITEFUNCTION, &curl_handle_write_sstream);
Expand Down
4 changes: 3 additions & 1 deletion src/sota_tools/oauth2.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ class OAuth2 {
/**
* Doesn't perform any authentication
*/
OAuth2(std::string server, std::string client_id, std::string client_secret, std::string ca_certs)
OAuth2(std::string server, std::string client_id, std::string client_secret, std::string scope, std::string ca_certs)
: server_(std::move(server)),
client_id_(std::move(client_id)),
client_secret_(std::move(client_secret)),
scope_(std::move(scope)),
ca_certs_(std::move(ca_certs)) {}

/**
Expand All @@ -28,6 +29,7 @@ class OAuth2 {
const std::string server_;
const std::string client_id_;
const std::string client_secret_;
const std::string scope_;
const std::string ca_certs_;
std::string token_;
};
Expand Down
1 change: 1 addition & 0 deletions src/sota_tools/server_credentials.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ ServerCredentials::ServerCredentials(const boost::filesystem::path &credentials_
auth_server_ = ap_pt->get<std::string>("server", "");
client_id_ = ap_pt->get<std::string>("client_id", "");
client_secret_ = ap_pt->get<std::string>("client_secret", "");
scope_ = ap_pt->get<std::string>("scope", "");
} else if (optional<ptree &> ba_pt = pt.get_child_optional("basic_auth")) {
method_ = AuthMethod::kBasic;
auth_user_ = ba_pt->get<std::string>("user", "");
Expand Down
2 changes: 2 additions & 0 deletions src/sota_tools/server_credentials.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class ServerCredentials {
std::string GetOSTreeServer() const { return ostree_server_; };
std::string GetClientId() const { return client_id_; };
std::string GetClientSecret() const { return client_secret_; };
std::string GetScope() const { return scope_; };

/**
* Path to the original credentials.zip on disk. Needed to hand off to
Expand All @@ -52,6 +53,7 @@ class ServerCredentials {
std::string ostree_server_;
std::string client_id_;
std::string client_secret_;
std::string scope_;
boost::filesystem::path credentials_path_;
};

Expand Down
11 changes: 11 additions & 0 deletions tests/sota_tools/auth_test_good_v2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"oauth2" : {
"server" : "https://ota-eks.auth.eu-west-1.amazoncognito.com/oauth2/token",
"client_id" : "77n69lb62l9ib2fpvgadh1unp2",
"client_secret" : "1ebijt9r6m6f6v6f0s8avh5qfk3s8it1teddicl36aem487tj6jf",
"scope" : "ota-treehub-0/namespace.default"
},
"ostree" : {
"server" : "http://treehub.banana.sit-ota.aws.in.here.com:80/api/v3"
}
}

0 comments on commit ebb75ad

Please sign in to comment.