summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorLiam Hopkins <liamh@google.com>2019-07-09 10:27:45 -0700
committerGitHub <noreply@github.com>2019-07-09 10:27:45 -0700
commit71385971da0612f87e8dcb87054b9b06138b703c (patch)
tree1cb62ee9ac855e6031f343f102d9f3640e021d53 /packages
parent22025ab58556b58432209b780b77819d2ecad4d2 (diff)
downloadgoogle-compute-image-packages-71385971da0612f87e8dcb87054b9b06138b703c.tar.gz
Groups (#784)
* Initial support for OS Login groups. * getgrnam/getgrgid lookups
Diffstat (limited to 'packages')
-rw-r--r--packages/google-compute-engine-oslogin/src/include/oslogin_utils.h57
-rw-r--r--packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc115
-rw-r--r--packages/google-compute-engine-oslogin/src/utils.cc278
-rw-r--r--packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc253
4 files changed, 569 insertions, 134 deletions
diff --git a/packages/google-compute-engine-oslogin/src/include/oslogin_utils.h b/packages/google-compute-engine-oslogin/src/include/oslogin_utils.h
index 6cd2024..ea8beae 100644
--- a/packages/google-compute-engine-oslogin/src/include/oslogin_utils.h
+++ b/packages/google-compute-engine-oslogin/src/include/oslogin_utils.h
@@ -12,8 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <grp.h>
#include <pthread.h>
#include <pwd.h>
+
#include <string>
#include <vector>
@@ -29,7 +31,7 @@ namespace oslogin_utils {
// Metadata server URL.
static const char kMetadataServerUrl[] =
- "http://metadata.google.internal/computeMetadata/v1/oslogin/";
+ "http://metadata.google.internal/computeMetadata/v1/oslogin/";
// BufferManager encapsulates and manages a buffer and length. This class is not
// thread safe.
@@ -44,9 +46,11 @@ class BufferManager {
// buffer for the string.
bool AppendString(const string& value, char** buffer, int* errnop);
+ // Return a pointer to a buffer of size bytes. Returns NULL and sets errnop to
+ // ERANGE if there is not enough space left in the buffer for the request.
+ void* Reserve(size_t bytes, int* errnop);
+
private:
- // Return a pointer to a buffer of size bytes.
- void* Reserve(size_t bytes);
// Whether there is space available in the buffer.
bool CheckSpaceAvailable(size_t bytes_to_write) const;
@@ -66,6 +70,12 @@ class Challenge {
string status;
};
+class Group {
+ public:
+ int64_t gid;
+ string name;
+};
+
// NssCache caches passwd entries for getpwent_r. This is used to prevent making
// an HTTP call on every getpwent_r invocation. Stores up to cache_size entries
// at a time. This class is not thread safe.
@@ -98,7 +108,8 @@ class NssCache {
// make an http call to the server if necessary to retrieve additional
// entries. Returns whether passwd retrieval was successful. If true, the
// passwd result will contain valid data.
- bool NssGetpwentHelper(BufferManager* buf, struct passwd* result, int* errnop);
+ bool NssGetpwentHelper(BufferManager* buf, struct passwd* result,
+ int* errnop);
// Returns the page token for requesting the next page of passwd entries.
string GetPageToken() { return page_token_; }
@@ -114,7 +125,7 @@ class NssCache {
std::string page_token_;
// Index for requesting the next passwd from the cache.
- int index_;
+ uint32_t index_;
// Whether the NssCache has reached the last page of the database.
bool on_last_page_;
@@ -144,8 +155,7 @@ class MutexLock {
};
// Callback invoked when Curl completes a request.
-size_t
-OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp);
+size_t OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp);
// Uses Curl to issue a GET request to the given url. Returns whether the
// request was successful. If successful, the result from the server will be
@@ -163,17 +173,42 @@ std::string UrlEncode(const string& param);
// Returns true if the given passwd contains valid fields. If pw_dir, pw_shell,
// or pw_passwd are not set, this will populate these entries with default
// values.
-bool ValidatePasswd(struct passwd* result, BufferManager* buf,
- int* errnop);
+bool ValidatePasswd(struct passwd* result, BufferManager* buf, int* errnop);
+
+// Adds users and associated array of char* to provided buffer and store pointer
+// to array in result.gr_mem.
+bool AddUsersToGroup(std::vector<string> users, struct group* result,
+ BufferManager* buf, int* errnop);
+
+// Iterates through all groups until one matching provided group is found,
+// replacing gr_name with a buffermanager provided string.
+bool FindGroup(struct group* grp, BufferManager* buf, int* errnop);
+
+// Iterates through all users for a group, storing results in a provided string
+// vector.
+bool GetUsersForGroup(string groupname, std::vector<string>* users,
+ int* errnop);
+
+// Iterates through all groups for a user, storing results in a provided string
+// vector.
+bool GetGroupsForUser(string username, std::vector<Group>* groups, int* errnop);
+
+// Parses a JSON groups response, storing results in a provided Group vector.
+bool ParseJsonToGroups(const string& json, std::vector<Group>* groups);
+
+// Parses a JSON users response, storing results in a provided string vector.
+bool ParseJsonToUsers(const string& json, std::vector<string>* users);
// Parses a JSON LoginProfiles response for SSH keys. Returns a vector of valid
// ssh_keys. A key is considered valid if it's expiration date is greater than
// current unix time.
std::vector<string> ParseJsonToSshKeys(const string& json);
+// Parses a JSON object and returns the value associated with a given key.
+bool ParseJsonToKey(const string& json, const string& key, string* response);
+
// Parses a JSON LoginProfiles response and returns the email under the "name"
// field.
-bool ParseJsonToKey(const string& json, const string& key, string* email);
bool ParseJsonToEmail(const string& json, string* email);
// Parses a JSON LoginProfiles response and populates the passwd struct with the
@@ -187,7 +222,7 @@ bool ParseJsonToPasswd(const string& response, struct passwd* result,
bool ParseJsonToSuccess(const string& json);
// Parses a JSON startSession response into a vector of Challenge objects.
-bool ParseJsonToChallenges(const string& json, vector<Challenge> *challenges);
+bool ParseJsonToChallenges(const string& json, vector<Challenge>* challenges);
// Calls the startSession API.
bool StartSession(const string& email, string* response);
diff --git a/packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc b/packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc
index 2f6245a..f928dcf 100644
--- a/packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc
+++ b/packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc
@@ -12,12 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <compat.h>
#include <curl/curl.h>
#include <errno.h>
#include <grp.h>
#include <nss.h>
+#include <oslogin_utils.h>
#include <pthread.h>
#include <pwd.h>
+#include <string.h>
+#include <sys/param.h>
#include <sys/types.h>
#include <syslog.h>
#include <unistd.h>
@@ -26,18 +30,20 @@
#include <sstream>
#include <string>
-#include <compat.h>
-#include <oslogin_utils.h>
-
using std::string;
+using oslogin_utils::AddUsersToGroup;
using oslogin_utils::BufferManager;
+using oslogin_utils::FindGroup;
+using oslogin_utils::GetGroupsForUser;
+using oslogin_utils::GetUsersForGroup;
+using oslogin_utils::Group;
using oslogin_utils::HttpGet;
+using oslogin_utils::kMetadataServerUrl;
using oslogin_utils::MutexLock;
using oslogin_utils::NssCache;
using oslogin_utils::ParseJsonToPasswd;
using oslogin_utils::UrlEncode;
-using oslogin_utils::kMetadataServerUrl;
// Size of the NssCache. This also determines how many users will be requested
// per HTTP call.
@@ -52,8 +58,9 @@ static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
extern "C" {
// Get a passwd entry by id.
-int _nss_oslogin_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
- size_t buflen, int *errnop) {
+enum nss_status _nss_oslogin_getpwuid_r(uid_t uid, struct passwd *result,
+ char *buffer, size_t buflen,
+ int *errnop) {
BufferManager buffer_manager(buffer, buflen);
std::stringstream url;
url << kMetadataServerUrl << "users?uid=" << uid;
@@ -77,8 +84,9 @@ int _nss_oslogin_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
}
// Get a passwd entry by name.
-int _nss_oslogin_getpwnam_r(const char *name, struct passwd *result,
- char *buffer, size_t buflen, int *errnop) {
+enum nss_status _nss_oslogin_getpwnam_r(const char *name, struct passwd *result,
+ char *buffer, size_t buflen,
+ int *errnop) {
BufferManager buffer_manager(buffer, buflen);
std::stringstream url;
url << kMetadataServerUrl << "users?username=" << UrlEncode(name);
@@ -101,6 +109,70 @@ int _nss_oslogin_getpwnam_r(const char *name, struct passwd *result,
return NSS_STATUS_SUCCESS;
}
+enum nss_status _nss_oslogin_getgrby(struct group *grp, char *buf,
+ size_t buflen, int *errnop) {
+ BufferManager buffer_manager(buf, buflen);
+ if (!FindGroup(grp, &buffer_manager, errnop))
+ return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
+
+ std::vector<string> users;
+ if (!GetUsersForGroup(grp->gr_name, &users, errnop))
+ return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
+
+ if (!AddUsersToGroup(users, grp, &buffer_manager, errnop))
+ return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
+
+ return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status _nss_oslogin_getgrgid_r(gid_t gid, struct group *grp, char *buf,
+ size_t buflen, int *errnop) {
+ grp->gr_gid = gid;
+ return _nss_oslogin_getgrby(grp, buf, buflen, errnop);
+}
+
+enum nss_status _nss_oslogin_getgrnam_r(const char *name, struct group *grp,
+ char *buf, size_t buflen, int *errnop) {
+ grp->gr_name = (char *)name;
+ return _nss_oslogin_getgrby(grp, buf, buflen, errnop);
+}
+
+enum nss_status _nss_oslogin_initgroups_dyn(const char *user, gid_t skipgroup,
+ long int *start, long int *size,
+ gid_t **groupsp, long int limit,
+ int *errnop) {
+ std::vector<Group> grouplist;
+ if (!GetGroupsForUser(string(user), &grouplist, errnop)) {
+ return NSS_STATUS_NOTFOUND;
+ }
+
+ gid_t *groups = *groupsp;
+ for (auto &group : grouplist) {
+ // Resize the buffer if needed.
+ if (*start == *size) {
+ gid_t *newgroups;
+ long int newsize = 2 * *size;
+ // Stop at limit if provided.
+ if (limit > 0) {
+ if (*size >= limit) {
+ *errnop = ERANGE;
+ return NSS_STATUS_TRYAGAIN;
+ }
+ newsize = MIN(limit, newsize);
+ }
+ newgroups = (gid_t *)realloc(groups, newsize * sizeof(gid_t *));
+ if (newgroups == NULL) {
+ *errnop = EAGAIN;
+ return NSS_STATUS_TRYAGAIN;
+ }
+ *groupsp = groups = newgroups;
+ *size = newsize;
+ }
+ groups[(*start)++] = group.gid;
+ }
+ return NSS_STATUS_SUCCESS;
+}
+
// nss_getpwent_r() is intentionally left unimplemented. This functionality is
// now covered by the nss_cache binary and nss_cache module.
@@ -113,19 +185,24 @@ NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r);
NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r);
NSS_METHOD_PROTOTYPE(__nss_compat_setpwent);
NSS_METHOD_PROTOTYPE(__nss_compat_endpwent);
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r);
DECLARE_NSS_METHOD_TABLE(methods,
- { NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r,
- (void*)_nss_oslogin_getpwnam_r },
- { NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r,
- (void*)_nss_oslogin_getpwuid_r },
- { NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r,
- (void*)_nss_oslogin_getpwent_r },
- { NSDB_PASSWD, "endpwent", __nss_compat_endpwent,
- (void*)_nss_oslogin_endpwent },
- { NSDB_PASSWD, "setpwent", __nss_compat_setpwent,
- (void*)_nss_oslogin_setpwent },
-)
+ {NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r,
+ (void *)_nss_oslogin_getpwnam_r},
+ {NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r,
+ (void *)_nss_oslogin_getpwuid_r},
+ {NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r,
+ (void *)_nss_oslogin_getpwent_r},
+ {NSDB_PASSWD, "endpwent", __nss_compat_endpwent,
+ (void *)_nss_oslogin_endpwent},
+ {NSDB_PASSWD, "setpwent", __nss_compat_setpwent,
+ (void *)_nss_oslogin_setpwent},
+ {NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r,
+ (void *)_nss_oslogin_getgrnam_r},
+ {NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r,
+ (void *)_nss_oslogin_getgrgid_r}, )
NSS_REGISTER_METHODS(methods)
} // extern "C"
diff --git a/packages/google-compute-engine-oslogin/src/utils.cc b/packages/google-compute-engine-oslogin/src/utils.cc
index 95f6c0b..ceda0af 100644
--- a/packages/google-compute-engine-oslogin/src/utils.cc
+++ b/packages/google-compute-engine-oslogin/src/utils.cc
@@ -15,18 +15,19 @@
// Requires libcurl4-openssl-dev libjson0 and libjson0-dev
#include <curl/curl.h>
#include <errno.h>
+#include <grp.h>
#include <json.h>
#include <nss.h>
#include <stdio.h>
#include <time.h>
+
#include <cstring>
#include <iostream>
#include <sstream>
#if defined(__clang__) || __GNUC__ > 4 || \
- (__GNUC__ == 4 && (__GNUC_MINOR__ > 9 || \
- (__GNUC_MINOR__ == 9 && \
- __GNUC_PATCHLEVEL__ > 0)))
+ (__GNUC__ == 4 && \
+ (__GNUC_MINOR__ > 9 || (__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 0)))
#include <regex>
#define Regex std
#else
@@ -34,8 +35,8 @@
#define Regex boost
#endif
-#include <oslogin_utils.h>
#include <compat.h>
+#include <oslogin_utils.h>
using std::string;
@@ -53,11 +54,10 @@ BufferManager::BufferManager(char* buf, size_t buflen)
bool BufferManager::AppendString(const string& value, char** buffer,
int* errnop) {
size_t bytes_to_write = value.length() + 1;
- if (!CheckSpaceAvailable(bytes_to_write)) {
- *errnop = ERANGE;
+ *buffer = static_cast<char*>(Reserve(bytes_to_write, errnop));
+ if (*buffer == NULL) {
return false;
}
- *buffer = static_cast<char*>(Reserve(bytes_to_write));
strncpy(*buffer, value.c_str(), bytes_to_write);
return true;
}
@@ -69,11 +69,10 @@ bool BufferManager::CheckSpaceAvailable(size_t bytes_to_write) const {
return true;
}
-void* BufferManager::Reserve(size_t bytes) {
- if (buflen_ < bytes) {
- std::cerr << "Attempted to reserve more bytes than the buffer can hold!"
- << "\n";
- abort();
+void* BufferManager::Reserve(size_t bytes, int* errnop) {
+ if (!CheckSpaceAvailable(bytes)) {
+ *errnop = ERANGE;
+ return NULL;
}
void* result = buf_;
buf_ += bytes;
@@ -95,7 +94,7 @@ void NssCache::Reset() {
}
bool NssCache::HasNextPasswd() {
- return index_ < passwd_cache_.size() && !passwd_cache_[index_].empty();
+ return (index_ < passwd_cache_.size()) && !passwd_cache_[index_].empty();
}
bool NssCache::GetNextPasswd(BufferManager* buf, passwd* result, int* errnop) {
@@ -172,7 +171,7 @@ bool NssCache::NssGetpwentHelper(BufferManager* buf, struct passwd* result,
response.empty() || !LoadJsonArrayToCache(response)) {
// It is possible this to be true after LoadJsonArrayToCache(), so we
// must check it again.
- if(!OnLastPage()) {
+ if (!OnLastPage()) {
*errnop = ENOENT;
}
return false;
@@ -268,8 +267,7 @@ string UrlEncode(const string& param) {
return encoded_param;
}
-bool ValidatePasswd(struct passwd* result, BufferManager* buf,
- int* errnop) {
+bool ValidatePasswd(struct passwd* result, BufferManager* buf, int* errnop) {
// OS Login disallows uids less than 1000.
if (result->pw_uid < 1000) {
*errnop = EINVAL;
@@ -307,6 +305,72 @@ bool ValidatePasswd(struct passwd* result, BufferManager* buf,
return true;
}
+bool ParseJsonToUsers(const string& json, std::vector<string>* result) {
+ json_object* root = NULL;
+ root = json_tokener_parse(json.c_str());
+ if (root == NULL) {
+ return false;
+ }
+
+ json_object* users = NULL;
+ if (!json_object_object_get_ex(root, "usernames", &users)) {
+ return false;
+ }
+ if (json_object_get_type(users) != json_type_array) {
+ return false;
+ }
+ for (int idx = 0; idx < json_object_array_length(users); idx++) {
+ json_object* user = json_object_array_get_idx(users, idx);
+ const char* username = json_object_get_string(user);
+ result->push_back(string(username));
+ }
+ return true;
+}
+
+bool ParseJsonToGroups(const string& json, std::vector<Group>* result) {
+ json_object* root = NULL;
+ root = json_tokener_parse(json.c_str());
+ if (root == NULL) {
+ return false;
+ }
+
+ json_object* groups = NULL;
+ if (!json_object_object_get_ex(root, "posixGroups", &groups)) {
+ return false;
+ }
+ if (json_object_get_type(groups) != json_type_array) {
+ return false;
+ }
+ for (int idx = 0; idx < json_object_array_length(groups); idx++) {
+ json_object* group = json_object_array_get_idx(groups, idx);
+
+ json_object* gid;
+ if (!json_object_object_get_ex(group, "gid", &gid)) {
+ return false;
+ }
+
+ json_object* name;
+ if (!json_object_object_get_ex(group, "name", &name)) {
+ return false;
+ }
+
+ Group g;
+ g.gid = json_object_get_int64(gid);
+ // get_int64 will confusingly return 0 if the string can't be converted to
+ // an integer. We can't rely on type check as it may be a string in the API.
+ if (g.gid == 0) {
+ return false;
+ }
+ g.name = json_object_get_string(name);
+ if (g.name == "") {
+ return false;
+ }
+
+ result->push_back(g);
+ }
+ return true;
+}
+
std::vector<string> ParseJsonToSshKeys(const string& json) {
std::vector<string> result;
json_object* root = NULL;
@@ -333,17 +397,14 @@ std::vector<string> ParseJsonToSshKeys(const string& json) {
if (json_object_get_type(ssh_public_keys) != json_type_object) {
return result;
}
- json_object_object_foreach(ssh_public_keys, key, val) {
- json_object* iter;
- if (!json_object_object_get_ex(ssh_public_keys, key, &iter)) {
- return result;
- }
- if (json_object_get_type(iter) != json_type_object) {
+ json_object_object_foreach(ssh_public_keys, key, obj) {
+ (void)(key);
+ if (json_object_get_type(obj) != json_type_object) {
continue;
}
string key_to_add = "";
bool expired = false;
- json_object_object_foreach(iter, key, val) {
+ json_object_object_foreach(obj, key, val) {
string string_key(key);
int val_type = json_object_get_type(val);
if (string_key == "key") {
@@ -470,6 +531,31 @@ bool ParseJsonToPasswd(const string& json, struct passwd* result,
return ValidatePasswd(result, buf, errnop);
}
+bool AddUsersToGroup(std::vector<string> users, struct group* result,
+ BufferManager* buf, int* errnop) {
+ if (users.size() < 1) {
+ return true;
+ }
+
+ // Get some space for the char* array for number of users + 1 for NULL cap.
+ char** bufp;
+ if (!(bufp =
+ (char**)buf->Reserve(sizeof(char*) * (users.size() + 1), errnop))) {
+ return false;
+ }
+ result->gr_mem = bufp;
+
+ for (auto& el : users) {
+ if (!buf->AppendString(el, bufp, errnop)) {
+ result->gr_mem = NULL;
+ return false;
+ }
+ }
+ *bufp = NULL; // End the array with a null pointer.
+
+ return true;
+}
+
bool ParseJsonToEmail(const string& json, string* email) {
json_object* root = NULL;
root = json_tokener_parse(json.c_str());
@@ -513,7 +599,7 @@ bool ParseJsonToKey(const string& json, const string& key, string* response) {
const char* c_response;
root = json_tokener_parse(json.c_str());
- if (root==NULL) {
+ if (root == NULL) {
return false;
}
@@ -530,7 +616,7 @@ bool ParseJsonToKey(const string& json, const string& key, string* response) {
}
bool ParseJsonToChallenges(const string& json,
- std::vector<Challenge> *challenges) {
+ std::vector<Challenge>* challenges) {
json_object* root = NULL;
root = json_tokener_parse(json.c_str());
@@ -538,7 +624,7 @@ bool ParseJsonToChallenges(const string& json,
return false;
}
- json_object *jsonChallenges = NULL;
+ json_object* jsonChallenges = NULL;
if (!json_object_object_get_ex(root, "challenges", &jsonChallenges)) {
return false;
}
@@ -568,13 +654,134 @@ bool ParseJsonToChallenges(const string& json,
return true;
}
+bool FindGroup(struct group* result, BufferManager* buf, int* errnop) {
+ if (result->gr_name == NULL && result->gr_gid == 0) {
+ return false;
+ }
+ std::stringstream url;
+ std::vector<Group> groups;
+
+ string response;
+ long http_code;
+ string pageToken = "";
+
+ do {
+ url.str("");
+ url << kMetadataServerUrl << "groups";
+ if (pageToken != "") url << "?pageToken=" << pageToken;
+
+ response.clear();
+ http_code = 0;
+ if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
+ response.empty()) {
+ *errnop = EAGAIN;
+ return false;
+ }
+
+ if (!ParseJsonToKey(response, "nextPageToken", &pageToken)) {
+ pageToken = "";
+ }
+
+ groups.clear();
+ if (!ParseJsonToGroups(response, &groups) || groups.empty()) {
+ *errnop = ENOENT;
+ return false;
+ }
+
+ // Check for a match.
+ for (auto& el : groups) {
+ if ((result->gr_name != NULL) && (string(result->gr_name) == el.name)) {
+ // Set the name even though it matches because the final string must
+ // be stored in the provided buffer.
+ if (!buf->AppendString(el.name, &result->gr_name, errnop)) {
+ return false;
+ }
+ result->gr_gid = el.gid;
+ return true;
+ }
+ if ((result->gr_gid != 0) && (result->gr_gid == el.gid)) {
+ if (!buf->AppendString(el.name, &result->gr_name, errnop)) {
+ return false;
+ }
+ return true;
+ }
+ }
+ } while (pageToken != "");
+ // Not found.
+ *errnop = ENOENT;
+ return false;
+}
+
+bool GetGroupsForUser(string username, std::vector<Group>* groups,
+ int* errnop) {
+ std::stringstream url;
+
+ string response;
+ long http_code;
+ string pageToken = "";
+
+ do {
+ url.str("");
+ url << kMetadataServerUrl << "groups?username=" << username;
+ if (pageToken != "") url << "?pageToken=" << pageToken;
+
+ response.clear();
+ http_code = 0;
+ if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
+ response.empty()) {
+ *errnop = EAGAIN;
+ return false;
+ }
+
+ if (!ParseJsonToKey(response, "pageToken", &pageToken)) {
+ pageToken = "";
+ }
+
+ if (!ParseJsonToGroups(response, groups)) {
+ *errnop = ENOENT;
+ return false;
+ }
+ } while (pageToken != "");
+ return true;
+}
+
+bool GetUsersForGroup(string groupname, std::vector<string>* users,
+ int* errnop) {
+ string response;
+ long http_code;
+ string pageToken = "";
+ std::stringstream url;
+
+ do {
+ url.str("");
+ url << kMetadataServerUrl << "users?groupname=" << groupname;
+ if (pageToken != "") url << "?pageToken=" << pageToken;
+
+ response.clear();
+ http_code = 0;
+ if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
+ response.empty()) {
+ *errnop = EAGAIN;
+ return false;
+ }
+ if (!ParseJsonToKey(response, "nextPageToken", &pageToken)) {
+ pageToken = "";
+ }
+ if (!ParseJsonToUsers(response, users)) {
+ *errnop = EINVAL;
+ return false;
+ }
+ } while (pageToken != "");
+ return true;
+}
+
bool GetUser(const string& username, string* response) {
std::stringstream url;
url << kMetadataServerUrl << "users?username=" << UrlEncode(username);
long http_code = 0;
- if (!HttpGet(url.str(), response, &http_code) || response->empty()
- || http_code != 200) {
+ if (!HttpGet(url.str(), response, &http_code) || response->empty() ||
+ http_code != 200) {
return false;
}
return true;
@@ -601,8 +808,8 @@ bool StartSession(const string& email, string* response) {
url << kMetadataServerUrl << "authenticate/sessions/start";
long http_code = 0;
- if (!HttpPost(url.str(), data, response, &http_code) || response->empty()
- || http_code != 200) {
+ if (!HttpPost(url.str(), data, response, &http_code) || response->empty() ||
+ http_code != 200) {
ret = false;
}
@@ -627,8 +834,7 @@ bool ContinueSession(bool alt, const string& email, const string& user_token,
json_object_object_add(jobj, "action",
json_object_new_string("START_ALTERNATE"));
} else {
- json_object_object_add(jobj, "action",
- json_object_new_string("RESPOND"));
+ json_object_object_add(jobj, "action", json_object_new_string("RESPOND"));
}
// AUTHZEN type and START_ALTERNATE action don't provide credentials.
@@ -643,11 +849,11 @@ bool ContinueSession(bool alt, const string& email, const string& user_token,
data = json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PLAIN);
std::stringstream url;
- url << kMetadataServerUrl << "authenticate/sessions/"
- << session_id << "/continue";
+ url << kMetadataServerUrl << "authenticate/sessions/" << session_id
+ << "/continue";
long http_code = 0;
- if (!HttpPost(url.str(), data, response, &http_code) || response->empty()
- || http_code != 200) {
+ if (!HttpPost(url.str(), data, response, &http_code) || response->empty() ||
+ http_code != 200) {
ret = false;
}
diff --git a/packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc b/packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc
index 657b4e1..6c9c1df 100644
--- a/packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc
+++ b/packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc
@@ -13,10 +13,9 @@
// limitations under the License.
// Requires libgtest-dev and gtest compiled and installed.
-#include <oslogin_utils.h>
-
#include <errno.h>
#include <gtest/gtest.h>
+#include <oslogin_utils.h>
#include <stdio.h>
#include <stdlib.h>
@@ -25,11 +24,10 @@ using std::vector;
namespace oslogin_utils {
-
// Test that the buffer can successfully append multiple strings.
TEST(BufferManagerTest, TestAppendString) {
size_t buflen = 20;
- char* buffer = (char*)malloc(buflen *sizeof(char));
+ char* buffer = (char*)malloc(buflen * sizeof(char));
ASSERT_STRNE(buffer, NULL);
char* first_string;
@@ -38,7 +36,7 @@ TEST(BufferManagerTest, TestAppendString) {
oslogin_utils::BufferManager buffer_manager(buffer, buflen);
buffer_manager.AppendString("test1", &first_string, &test_errno);
buffer_manager.AppendString("test2", &second_string, &test_errno);
- EXPECT_EQ(test_errno, 0);
+ ASSERT_EQ(test_errno, 0);
ASSERT_STREQ(first_string, "test1");
ASSERT_STREQ(second_string, "test2");
ASSERT_STREQ(buffer, "test1");
@@ -57,7 +55,7 @@ TEST(BufferManagerTest, TestAppendStringTooLarge) {
oslogin_utils::BufferManager buffer_manager(buffer, buflen);
ASSERT_FALSE(
buffer_manager.AppendString("test1", &first_string, &test_errno));
- EXPECT_EQ(test_errno, ERANGE);
+ ASSERT_EQ(test_errno, ERANGE);
}
// Test successfully loading and retrieving an array of JSON posix accounts.
@@ -87,9 +85,9 @@ TEST(NssCacheTest, TestLoadJsonArray) {
// Verify that the first user was stored.
ASSERT_TRUE(nss_cache.HasNextPasswd());
ASSERT_TRUE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- EXPECT_EQ(test_errno, 0);
- EXPECT_EQ(result.pw_uid, 1337);
- EXPECT_EQ(result.pw_gid, 1337);
+ ASSERT_EQ(test_errno, 0);
+ ASSERT_EQ(result.pw_uid, 1337);
+ ASSERT_EQ(result.pw_gid, 1337);
ASSERT_STREQ(result.pw_name, "foo");
ASSERT_STREQ(result.pw_shell, "/bin/bash");
ASSERT_STREQ(result.pw_dir, "/home/foo");
@@ -97,9 +95,9 @@ TEST(NssCacheTest, TestLoadJsonArray) {
// Verify that the second user was stored.
ASSERT_TRUE(nss_cache.HasNextPasswd());
ASSERT_TRUE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- EXPECT_EQ(test_errno, 0);
- EXPECT_EQ(result.pw_uid, 1338);
- EXPECT_EQ(result.pw_gid, 1338);
+ ASSERT_EQ(test_errno, 0);
+ ASSERT_EQ(result.pw_uid, 1338);
+ ASSERT_EQ(result.pw_gid, 1338);
ASSERT_STREQ(result.pw_name, "bar");
ASSERT_STREQ(result.pw_shell, "/bin/bash");
ASSERT_STREQ(result.pw_dir, "/home/bar");
@@ -107,7 +105,7 @@ TEST(NssCacheTest, TestLoadJsonArray) {
// Verify that there are no more users stored.
ASSERT_FALSE(nss_cache.HasNextPasswd());
ASSERT_FALSE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- EXPECT_EQ(test_errno, ENOENT);
+ ASSERT_EQ(test_errno, ENOENT);
}
// Test successfully loading and retrieving a partial array.
@@ -132,9 +130,9 @@ TEST(NssCacheTest, TestLoadJsonPartialArray) {
// Verify that the first user was stored.
ASSERT_TRUE(nss_cache.HasNextPasswd());
ASSERT_TRUE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- EXPECT_EQ(test_errno, 0);
- EXPECT_EQ(result.pw_uid, 1337);
- EXPECT_EQ(result.pw_gid, 1337);
+ ASSERT_EQ(test_errno, 0);
+ ASSERT_EQ(result.pw_uid, 1337);
+ ASSERT_EQ(result.pw_gid, 1337);
ASSERT_STREQ(result.pw_name, "foo");
ASSERT_STREQ(result.pw_shell, "/bin/bash");
ASSERT_STREQ(result.pw_dir, "/home/foo");
@@ -144,14 +142,13 @@ TEST(NssCacheTest, TestLoadJsonPartialArray) {
// Verify that there are no more users stored.
ASSERT_FALSE(nss_cache.HasNextPasswd());
ASSERT_FALSE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- EXPECT_EQ(test_errno, ENOENT);
+ ASSERT_EQ(test_errno, ENOENT);
}
// Test successfully loading and retrieving the final response.
TEST(NssCacheTest, TestLoadJsonFinalResponse) {
NssCache nss_cache(2);
- string response =
- "{\"nextPageToken\": \"0\"}";
+ string response = "{\"nextPageToken\": \"0\"}";
ASSERT_FALSE(nss_cache.LoadJsonArrayToCache(response));
ASSERT_EQ(nss_cache.GetPageToken(), "");
@@ -167,10 +164,9 @@ TEST(NssCacheTest, TestLoadJsonFinalResponse) {
ASSERT_FALSE(nss_cache.HasNextPasswd());
ASSERT_TRUE(nss_cache.OnLastPage());
ASSERT_FALSE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- EXPECT_EQ(test_errno, ENOENT);
+ ASSERT_EQ(test_errno, ENOENT);
}
-
// Tests that resetting, and checking HasNextPasswd does not crash.
TEST(NssCacheTest, ResetNullPtrTest) {
NssCache nss_cache(2);
@@ -192,8 +188,8 @@ TEST(ParseJsonPasswdTest, ParseJsonToPasswdSucceeds) {
struct passwd result;
int test_errno = 0;
ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- EXPECT_EQ(result.pw_uid, 1337);
- EXPECT_EQ(result.pw_gid, 1338);
+ ASSERT_EQ(result.pw_uid, 1337);
+ ASSERT_EQ(result.pw_gid, 1338);
ASSERT_STREQ(result.pw_name, "foo");
ASSERT_STREQ(result.pw_shell, "/bin/bash");
ASSERT_STREQ(result.pw_dir, "/home/foo");
@@ -213,8 +209,8 @@ TEST(ParseJsonPasswdTest, ParseJsonToPasswdSucceedsWithHighUid) {
struct passwd result;
int test_errno = 0;
ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- EXPECT_EQ(result.pw_uid, 4294967295);
- EXPECT_EQ(result.pw_gid, 4294967295);
+ ASSERT_EQ(result.pw_uid, 4294967295);
+ ASSERT_EQ(result.pw_gid, 4294967295);
ASSERT_STREQ(result.pw_name, "foo");
ASSERT_STREQ(result.pw_shell, "/bin/bash");
ASSERT_STREQ(result.pw_dir, "/home/foo");
@@ -233,8 +229,8 @@ TEST(ParseJsonPasswdTest, ParseJsonToPasswdSucceedsWithStringUid) {
struct passwd result;
int test_errno = 0;
ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- EXPECT_EQ(result.pw_uid, 1337);
- EXPECT_EQ(result.pw_gid, 1338);
+ ASSERT_EQ(result.pw_uid, 1337);
+ ASSERT_EQ(result.pw_gid, 1338);
ASSERT_STREQ(result.pw_name, "foo");
ASSERT_STREQ(result.pw_shell, "/bin/bash");
ASSERT_STREQ(result.pw_dir, "/home/foo");
@@ -253,8 +249,8 @@ TEST(ParseJsonPasswdTest, ParseJsonToPasswdNoLoginProfilesSucceeds) {
struct passwd result;
int test_errno = 0;
ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- EXPECT_EQ(result.pw_uid, 1337);
- EXPECT_EQ(result.pw_gid, 1337);
+ ASSERT_EQ(result.pw_uid, 1337);
+ ASSERT_EQ(result.pw_gid, 1337);
ASSERT_STREQ(result.pw_name, "foo");
ASSERT_STREQ(result.pw_shell, "/bin/bash");
ASSERT_STREQ(result.pw_dir, "/home/foo");
@@ -274,7 +270,7 @@ TEST(ParseJsonPasswdTest, ParseJsonToPasswdFailsWithERANGE) {
struct passwd result;
int test_errno = 0;
ASSERT_FALSE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- EXPECT_EQ(test_errno, ERANGE);
+ ASSERT_EQ(test_errno, ERANGE);
}
// Test parsing malformed JSON responses.
@@ -297,13 +293,13 @@ TEST(ParseJsonPasswdTest, ParseJsonToPasswdFailsWithEINVAL) {
struct passwd result;
int test_errno = 0;
ASSERT_FALSE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- EXPECT_EQ(test_errno, EINVAL);
+ ASSERT_EQ(test_errno, EINVAL);
// Reset errno.
test_errno = 0;
ASSERT_TRUE(ParseJsonToPasswd(test_user2, &result, &buf, &test_errno));
- EXPECT_EQ(test_errno, 0);
- EXPECT_EQ(result.pw_uid, 1337);
- EXPECT_EQ(result.pw_gid, 1337);
+ ASSERT_EQ(test_errno, 0);
+ ASSERT_EQ(result.pw_uid, 1337);
+ ASSERT_EQ(result.pw_gid, 1337);
}
// Test parsing a partially filled response. Validate should fill empty fields
@@ -321,8 +317,8 @@ TEST(ParseJsonPasswdTest, ValidatePartialJsonResponse) {
struct passwd result;
int test_errno = 0;
ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- EXPECT_EQ(result.pw_uid, 1337);
- EXPECT_EQ(result.pw_gid, 1337);
+ ASSERT_EQ(result.pw_uid, 1337);
+ ASSERT_EQ(result.pw_gid, 1337);
ASSERT_STREQ(result.pw_name, "foo");
ASSERT_STREQ(result.pw_shell, "/bin/bash");
ASSERT_STREQ(result.pw_dir, "/home/foo");
@@ -343,7 +339,139 @@ TEST(ParseJsonPasswdTest, ValidateInvalidJsonResponse) {
struct passwd result;
int test_errno = 0;
ASSERT_FALSE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- EXPECT_EQ(test_errno, EINVAL);
+ ASSERT_EQ(test_errno, EINVAL);
+}
+
+// Test parsing a valid JSON response from the metadata server.
+TEST(ParseJsonToGroupsTest, ParseJsonToGroupsSucceeds) {
+ string test_group = "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":123452}]}";
+
+ std::vector<Group> groups;
+ ASSERT_TRUE(ParseJsonToGroups(test_group, &groups));
+ ASSERT_EQ(groups[0].gid, 123452);
+ ASSERT_EQ(groups[0].name, "demo");
+}
+
+// Test parsing a valid JSON response from the metadata server with gid > 2^31.
+TEST(ParseJsonToGroupsTest, ParseJsonToGroupsSucceedsWithHighGid) {
+ string test_group =
+ "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":4294967295}]}";
+
+ std::vector<Group> groups;
+ ASSERT_TRUE(ParseJsonToGroups(test_group, &groups));
+ ASSERT_EQ(groups[0].gid, 4294967295);
+ ASSERT_EQ(groups[0].name, "demo");
+}
+
+TEST(ParseJsonToGroupsTest, ParseJsonToGroupsSucceedsWithStringGid) {
+ string test_group =
+ "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":\"123452\"}]}";
+
+ std::vector<Group> groups;
+ ASSERT_TRUE(ParseJsonToGroups(test_group, &groups));
+ ASSERT_EQ(groups[0].gid, 123452);
+ ASSERT_EQ(groups[0].name, "demo");
+}
+
+// Test parsing malformed JSON responses.
+TEST(ParseJsonToGroupsTest, ParseJsonToGroupsFails) {
+ string test_badgid =
+ "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":\"this-should-be-int\"}]}";
+ string test_nogid = "{\"posixGroups\":[{\"name\":\"demo\"}]}";
+ string test_noname = "{\"posixGroups\":[{\"gid\":123452}]}";
+
+ std::vector<Group> groups;
+ ASSERT_FALSE(ParseJsonToGroups(test_badgid, &groups));
+ ASSERT_FALSE(ParseJsonToGroups(test_nogid, &groups));
+ ASSERT_FALSE(ParseJsonToGroups(test_noname, &groups));
+}
+
+// Test parsing a valid JSON response from the metadata server.
+TEST(ParseJsonToUsersTest, ParseJsonToUsersSucceeds) {
+ string test_group_users =
+ "{\"usernames\":[\"user0001\",\"user0002\",\"user0003\",\"user0004\","
+ "\"user0005\"]}";
+
+ std::vector<string> users;
+ ASSERT_TRUE(ParseJsonToUsers(test_group_users, &users));
+ ASSERT_FALSE(users.empty());
+ ASSERT_EQ(users.size(), 5);
+
+ ASSERT_EQ(users[0], "user0001");
+ ASSERT_EQ(users[1], "user0002");
+ ASSERT_EQ(users[2], "user0003");
+ ASSERT_EQ(users[3], "user0004");
+ ASSERT_EQ(users[4], "user0005");
+}
+
+// Test parsing a valid JSON response from the metadata server.
+TEST(ParseJsonToUsersTest, ParseJsonToUsersEmptyGroupSucceeds) {
+ string test_group_users = "{\"usernames\":[]}";
+
+ std::vector<string> users;
+ ASSERT_TRUE(ParseJsonToUsers(test_group_users, &users));
+ ASSERT_TRUE(users.empty());
+}
+
+// Test parsing malformed JSON responses.
+TEST(ParseJsonToUsersTest, ParseJsonToUsersFails) {
+ string test_group_users =
+ "{\"badstuff\":[\"user0001\",\"user0002\",\"user0003\",\"user0004\","
+ "\"user0005\"]}";
+
+ std::vector<string> users;
+ ASSERT_FALSE(ParseJsonToUsers(test_group_users, &users));
+}
+
+TEST(GetUsersForGroupTest, GetUsersForGroupSucceeds) {
+ string response;
+ long http_code;
+ ASSERT_TRUE(
+ HttpGet("http://metadata.google.internal/reset", &response, &http_code));
+
+ std::vector<string> users;
+ int errnop = 0;
+
+ ASSERT_TRUE(GetUsersForGroup("demo", &users, &errnop));
+ ASSERT_FALSE(users.empty());
+ ASSERT_EQ(users[0], "user000173_grande_focustest_org");
+ ASSERT_EQ(errnop, 0);
+}
+
+TEST(FindGroupTest, FindGroupByGidSucceeds) {
+ string response;
+ long http_code;
+ ASSERT_TRUE(
+ HttpGet("http://metadata.google.internal/reset", &response, &http_code));
+
+ size_t buflen = 200 * sizeof(char);
+ char* buffer = (char*)malloc(buflen);
+ ASSERT_STRNE(buffer, NULL);
+ BufferManager buf(buffer, buflen);
+ int errnop = 0;
+
+ struct group grp = {};
+ grp.gr_gid = 123452;
+ ASSERT_TRUE(FindGroup(&grp, &buf, &errnop));
+ ASSERT_EQ(errnop, 0);
+}
+
+TEST(FindGroupTest, FindGroupByNameSucceeds) {
+ string response;
+ long http_code;
+ ASSERT_TRUE(
+ HttpGet("http://metadata.google.internal/reset", &response, &http_code));
+
+ size_t buflen = 200 * sizeof(char);
+ char* buffer = (char*)malloc(buflen);
+ ASSERT_STRNE(buffer, NULL);
+ BufferManager buf(buffer, buflen);
+ int errnop;
+
+ const char* match = "demo";
+ struct group grp = {};
+ grp.gr_name = (char*)match;
+ ASSERT_TRUE(FindGroup(&grp, &buf, &errnop));
}
TEST(ParseJsonEmailTest, SuccessfullyParsesEmail) {
@@ -372,10 +500,9 @@ TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysSucceeds) {
char* buffer = (char*)malloc(buflen * sizeof(char));
ASSERT_STRNE(buffer, NULL);
BufferManager buf(buffer, buflen);
- int test_errno = 0;
std::vector<string> result = ParseJsonToSshKeys(test_user);
- EXPECT_EQ(result.size(), 1);
- EXPECT_EQ(result[0], "test_key");
+ ASSERT_EQ(result.size(), 1);
+ ASSERT_EQ(result[0], "test_key");
}
TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysMultipleKeys) {
@@ -388,11 +515,10 @@ TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysMultipleKeys) {
char* buffer = (char*)malloc(buflen * sizeof(char));
ASSERT_STRNE(buffer, NULL);
BufferManager buf(buffer, buflen);
- int test_errno = 0;
std::vector<string> result = ParseJsonToSshKeys(test_user);
- EXPECT_EQ(result.size(), 2);
- EXPECT_EQ(result[0], "test_key");
- EXPECT_EQ(result[1], "test_key2");
+ ASSERT_EQ(result.size(), 2);
+ ASSERT_EQ(result[0], "test_key");
+ ASSERT_EQ(result[1], "test_key2");
}
TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysFiltersExpiredKeys) {
@@ -405,10 +531,9 @@ TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysFiltersExpiredKeys) {
char* buffer = (char*)malloc(buflen * sizeof(char));
ASSERT_STRNE(buffer, NULL);
BufferManager buf(buffer, buflen);
- int test_errno = 0;
std::vector<string> result = ParseJsonToSshKeys(test_user);
- EXPECT_EQ(result.size(), 1);
- EXPECT_EQ(result[0], "test_key");
+ ASSERT_EQ(result.size(), 1);
+ ASSERT_EQ(result[0], "test_key");
}
TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysFiltersMalformedExpiration) {
@@ -421,10 +546,9 @@ TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysFiltersMalformedExpiration) {
char* buffer = (char*)malloc(buflen * sizeof(char));
ASSERT_STRNE(buffer, NULL);
BufferManager buf(buffer, buflen);
- int test_errno = 0;
std::vector<string> result = ParseJsonToSshKeys(test_user);
- EXPECT_EQ(result.size(), 1);
- EXPECT_EQ(result[0], "test_key");
+ ASSERT_EQ(result.size(), 1);
+ ASSERT_EQ(result[0], "test_key");
}
TEST(ParseJsonAuthorizeSuccess, SuccessfullyAuthorized) {
@@ -433,16 +557,8 @@ TEST(ParseJsonAuthorizeSuccess, SuccessfullyAuthorized) {
}
TEST(ValidateUserNameTest, ValidateValidUserNames) {
- string cases[] = {
- "user",
- "_",
- ".",
- ".abc_",
- "_abc-",
- "ABC",
- "A_.-",
- "ausernamethirtytwocharacterslong"
- };
+ string cases[] = {"user", "_", ".", ".abc_",
+ "_abc-", "ABC", "A_.-", "ausernamethirtytwocharacterslong"};
for (auto test_user : cases) {
ASSERT_TRUE(ValidateUserName(test_user));
}
@@ -482,29 +598,30 @@ TEST(ParseJsonKeyTest, TestMissingKey) {
}
TEST(ParseJsonChallengesTest, TestChallenges) {
- string challenges_json = "{\"status\":\"CHALLENGE_REQUIRED\",\"sessionId\":"
+ string challenges_json =
+ "{\"status\":\"CHALLENGE_REQUIRED\",\"sessionId\":"
"\"testSessionId\",\"challenges\":[{\"challengeId\":1,\"challengeType\":"
"\"TOTP\",\"status\":\"READY\"}, {\"challengeId\":2,\"challengeType\":"
"\"AUTHZEN\",\"status\":\"PROPOSED\"}]}";
vector<Challenge> challenges;
ASSERT_TRUE(ParseJsonToChallenges(challenges_json, &challenges));
- EXPECT_EQ(challenges.size(), 2);
- EXPECT_EQ(challenges[0].id, 1);
- EXPECT_EQ(challenges[0].type, "TOTP");
+ ASSERT_EQ(challenges.size(), 2);
+ ASSERT_EQ(challenges[0].id, 1);
+ ASSERT_EQ(challenges[0].type, "TOTP");
}
TEST(ParseJsonChallengesTest, TestMalformedChallenges) {
- string challenges_json = "{\"status\":\"CHALLENGE_REQUIRED\",\"sessionId\":"
+ string challenges_json =
+ "{\"status\":\"CHALLENGE_REQUIRED\",\"sessionId\":"
"\"testSessionId\",\"challenges\":[{\"challengeId\":1,\"challengeType\":"
"\"TOTP\",\"status\":\"READY\"}, {\"challengeId\":2,\"challengeType\":"
"\"AUTHZEN\"}]}";
vector<Challenge> challenges;
ASSERT_FALSE(ParseJsonToChallenges(challenges_json, &challenges));
- EXPECT_EQ(challenges.size(), 1);
+ ASSERT_EQ(challenges.size(), 1);
}
} // namespace oslogin_utils
-
-int main(int argc, char **argv) {
+int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}