// ----------------------------------------------------------------------
// File: com_vid.cc
// Author: Andreas-Joachim Peters - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2011 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
/*----------------------------------------------------------------------------*/
#include "console/ConsoleMain.hh"
#include "common/StringTokenizer.hh"
#include "common/ParseUtils.hh"
/*----------------------------------------------------------------------------*/
/* VID System listing, configuration, manipulation */
int
com_vid(char* arg1)
{
// split subcommands
eos::common::StringTokenizer subtokenizer(arg1);
subtokenizer.GetLine();
XrdOucString subcommand = subtokenizer.GetTokenUnquoted();
if (wants_help(arg1)) {
goto com_vid_usage;
}
if (subcommand == "ls") {
XrdOucString in = "mgm.cmd=vid&mgm.subcmd=ls";
XrdOucString soption = "";
XrdOucString option = "";
do {
option = subtokenizer.GetTokenUnquoted();
if (option.beginswith("-")) {
option.erase(0, 1);
soption += option;
if (option.beginswith("h") || option.beginswith("-h")) {
goto com_vid_usage;
}
}
} while (option.length());
if (soption.length()) {
in += "&mgm.vid.option=";
in += soption;
}
global_retc = output_result(client_command(in, true));
return (0);
}
if (subcommand == "set") {
XrdOucString in = "mgm.cmd=vid&mgm.subcmd=set";
XrdOucString key = subtokenizer.GetTokenUnquoted();
if (!key.length()) {
goto com_vid_usage;
}
if (key.beginswith("-h") || key.beginswith("=-h")) {
goto com_vid_usage;
}
XrdOucString vidkey = "";
if (key == "geotag") {
XrdOucString match = subtokenizer.GetTokenUnquoted();
if (!match.length()) {
goto com_vid_usage;
}
if (match.beginswith("-h") || match.beginswith("=-h")) {
goto com_vid_usage;
}
XrdOucString target = subtokenizer.GetTokenUnquoted();
if (!target.length()) {
goto com_vid_usage;
}
// Check if geotag is valid
std::string geotag = eos::common::SanitizeGeoTag(target.c_str());
if (geotag != target.c_str()) {
fprintf(stderr, "%s\n", geotag.c_str());
return 0;
}
vidkey = "geotag:";
vidkey += match;
in += "&mgm.vid.cmd=geotag";
in += "&mgm.vid.key=";
in += vidkey.c_str();
in += "&mgm.vid.geotag=";
in += target.c_str();
global_retc = output_result(client_command(in, true));
return (0);
}
if (key == "membership") {
XrdOucString uid = subtokenizer.GetTokenUnquoted();
if (!uid.length()) {
goto com_vid_usage;
}
if (uid.beginswith("-h") || uid.beginswith("=-h")) {
goto com_vid_usage;
}
vidkey += uid;
XrdOucString type = subtokenizer.GetTokenUnquoted();
if (!type.length()) {
goto com_vid_usage;
}
in += "&mgm.vid.cmd=membership";
in += "&mgm.vid.source.uid=";
in += uid;
XrdOucString list = "";
if ((type == "-uids")) {
vidkey += ":uids";
list = subtokenizer.GetTokenUnquoted();
in += "&mgm.vid.key=";
in += vidkey;
in += "&mgm.vid.target.uid=";
in += list;
}
if ((type == "-gids")) {
vidkey += ":gids";
list = subtokenizer.GetTokenUnquoted();
in += "&mgm.vid.key=";
in += vidkey;
in += "&mgm.vid.target.gid=";
in += list;
}
if ((type == "+sudo")) {
vidkey += ":root";
list = " "; // fake
in += "&mgm.vid.key=";
in += vidkey;
in += "&mgm.vid.target.sudo=true";
}
if ((type == "-sudo")) {
vidkey += ":root";
list = " "; // fake
in += "&mgm.vid.key=";
in += vidkey;
in += "&mgm.vid.target.sudo=false";
}
if (!list.length()) {
goto com_vid_usage;
}
global_retc = output_result(client_command(in, true));
return (0);
}
if (key == "map") {
in += "&mgm.vid.cmd=map";
XrdOucString type = subtokenizer.GetTokenUnquoted();
if (!type.length()) {
goto com_vid_usage;
}
if ((type.beginswith("-h") || type.beginswith("=-h")) && (type != "-https")) {
goto com_vid_usage;
}
bool hastype = false;
if ((type == "-krb5")) {
in += "&mgm.vid.auth=krb5";
hastype = true;
}
if ((type == "-gsi")) {
in += "&mgm.vid.auth=gsi";
hastype = true;
}
if ((type == "-https")) {
in += "&mgm.vid.auth=https";
hastype = true;
}
if ((type == "-sss")) {
in += "&mgm.vid.auth=sss";
hastype = true;
}
if ((type == "-unix")) {
in += "&mgm.vid.auth=unix";
hastype = true;
}
if ((type == "-tident")) {
in += "&mgm.vid.auth=tident";
hastype = true;
}
if ((type == "-voms")) {
in += "&mgm.vid.auth=voms";
hastype = true;
}
if ((type == "-grpc")) {
in += "&mgm.vid.auth=grpc";
hastype = true;
}
if ((type == "-oauth2")) {
in += "&mgm.vid.auth=oauth2";
hastype = true;
}
if (!hastype) {
goto com_vid_usage;
}
XrdOucString pattern = subtokenizer.GetTokenUnquoted();
// deal with patterns containing spaces but inside ""
if (pattern.beginswith("\"")) {
if (!pattern.endswith("\""))
do {
XrdOucString morepattern = subtokenizer.GetTokenUnquoted();
if (morepattern.endswith("\"")) {
pattern += " ";
pattern += morepattern;
break;
}
if (!morepattern.length()) {
goto com_vid_usage;
}
pattern += " ";
pattern += morepattern;
} while (1);
}
if (!pattern.length()) {
goto com_vid_usage;
}
in += "&mgm.vid.pattern=";
in += pattern;
XrdOucString vid = subtokenizer.GetTokenUnquoted();
if (!vid.length()) {
goto com_vid_usage;
}
if (vid.beginswith("vuid:")) {
vid.replace("vuid:", "");
in += "&mgm.vid.uid=";
in += vid;
XrdOucString vid = subtokenizer.GetTokenUnquoted();
if (vid.length()) {
if (vid.beginswith("vgid:")) {
vid.replace("vgid:", "");
in += "&mgm.vid.gid=";
in += vid;
} else {
goto com_vid_usage;
}
}
} else {
if (vid.beginswith("vgid:")) {
vid.replace("vgid:", "");
in += "&mgm.vid.gid=";
in += vid;
} else {
goto com_vid_usage;
}
}
in += "&mgm.vid.key=";
in += "";
global_retc = output_result(client_command(in, true));
return (0);
}
}
if ((subcommand == "enable") || (subcommand == "disable")) {
XrdOucString in = "mgm.cmd=vid&mgm.subcmd=set&mgm.vid.cmd=map";
XrdOucString disableu =
"mgm.cmd=vid&mgm.subcmd=rm&mgm.vid.cmd=unmap&mgm.vid.key=";
XrdOucString disableg =
"mgm.cmd=vid&mgm.subcmd=rm&mgm.vid.cmd=unmap&mgm.vid.key=";
XrdOucString type = subtokenizer.GetTokenUnquoted();
if (!type.length()) {
goto com_vid_usage;
}
if (type.beginswith("-h") || type.beginswith("--h")) {
goto com_vid_usage;
}
bool hastype = false;
if ((type == "krb5")) {
in += "&mgm.vid.auth=krb5";
disableu += "krb5:\"\":uid";
disableg += "krb5:\"\":gid";
hastype = true;
}
if ((type == "sss")) {
in += "&mgm.vid.auth=sss";
disableu += "sss:\"\":uid";
disableg += "sss:\"\":gid";
hastype = true;
}
if ((type == "gsi")) {
in += "&mgm.vid.auth=gsi";
disableu += "gsi:\"\":uid";
disableg += "gsi:\"\":gid";
hastype = true;
}
if ((type == "https")) {
in += "&mgm.vid.auth=https";
disableu += "https:\"\":uid";
disableg += "https:\"\":gid";
hastype = true;
}
if ((type == "unix")) {
in += "&mgm.vid.auth=unix";
disableu += "unix:\"\":uid";
disableg += "unix:\"\":gid";
hastype = true;
}
if ((type == "grpc")) {
in += "&mgm.vid.auth=grpc";
disableu += "grpc:\"\":uid";
disableg += "grpc:\"\":gid";
hastype = true;
}
if ((type == "oauth2")) {
in += "&mgm.vid.auth=oauth2";
disableu += "oauth2:\"\":uid";
disableg += "oauth2:\"\":gid";
hastype = true;
}
if ((type == "tident")) {
in += "&mgm.vid.auth=tident";
disableu += "tident:\"\":uid";
disableg += "tident:\"\":gid";
hastype = true;
}
if ((type == "ztn")) {
in += "&mgm.vid.auth=ztn";
disableu += "ztn:\"\":uid";
disableg += "ztn:\"\":gid";
hastype = true;
}
if (!hastype) {
goto com_vid_usage;
}
in += "&mgm.vid.pattern=";
if (type != "unix") {
in += "&mgm.vid.uid=0";
in += "&mgm.vid.gid=0";
} else {
in += "&mgm.vid.uid=99";
in += "&mgm.vid.gid=99";
}
in += "&mgm.vid.key=";
in += "";
if ((subcommand == "enable")) {
global_retc = output_result(client_command(in, true));
}
if ((subcommand == "disable")) {
global_retc = output_result(client_command(disableu, true));
global_retc |= output_result(client_command(disableg, true));
}
return (0);
}
if (subcommand == "publicaccesslevel") {
XrdOucString in = "mgm.cmd=vid&mgm.subcmd=set";
XrdOucString vidkey = "";
XrdOucString level = subtokenizer.GetTokenUnquoted();
if (!level.length()) {
goto com_vid_usage;
}
if (level.beginswith("-h") || level.beginswith("=-h")) {
goto com_vid_usage;
}
vidkey = "publicaccesslevel";
in += "&mgm.vid.cmd=publicaccesslevel";
in += "&mgm.vid.key=";
in += vidkey.c_str();
in += "&mgm.vid.level=";
in += level.c_str();
global_retc = output_result(client_command(in, true));
return (0);
}
if (subcommand == "tokensudo") {
XrdOucString in = "mgm.cmd=vid&mgm.subcmd=set";
XrdOucString vidkey = "";
XrdOucString level = subtokenizer.GetTokenUnquoted();
if (!level.length()) {
goto com_vid_usage;
}
if (level.beginswith("-h") || level.beginswith("=-h")) {
goto com_vid_usage;
}
vidkey = "tokensudo";
in += "&mgm.vid.cmd=tokensudo";
in += "&mgm.vid.key=";
in += vidkey.c_str();
in += "&mgm.vid.tokensudo=";
in += level.c_str();
global_retc = output_result(client_command(in, true));
return (0);
}
if ((subcommand == "add") || (subcommand == "remove")) {
XrdOucString gw = subtokenizer.GetTokenUnquoted();
if (gw != "gateway") {
goto com_vid_usage;
}
XrdOucString host = subtokenizer.GetTokenUnquoted();
if (!host.length()) {
goto com_vid_usage;
}
XrdOucString protocol = subtokenizer.GetTokenUnquoted();
if (protocol.length() &&
((protocol != "sss") && (protocol != "gsi") &&
(protocol != "krb5") && (protocol != "unix") && (protocol != "https") &&
(protocol != "grpc") && (protocol != "outh2"))) {
goto com_vid_usage;
}
if (!protocol.length()) {
protocol = "*";
}
XrdOucString in = "mgm.cmd=vid&mgm.subcmd=set&mgm.vid.cmd=map";
XrdOucString disableu =
"mgm.cmd=vid&mgm.subcmd=rm&mgm.vid.cmd=unmap&mgm.vid.key=";
XrdOucString disableg =
"mgm.cmd=vid&mgm.subcmd=rm&mgm.vid.cmd=unmap&mgm.vid.key=";
in += "&mgm.vid.auth=tident";
in += "&mgm.vid.pattern=\"";
in += protocol;
in += "@";
in += host;
in += "\"";
in += "&mgm.vid.uid=0";
in += "&mgm.vid.gid=0";
disableu += "tident:\"";
disableu += protocol;
disableu += "@";
disableu += host;
disableu += "\":uid";
disableg += "tident:\"";
disableg += protocol;
disableg += "@";
disableg += host;
disableg += "\":gid";
in += "&mgm.vid.key=";
in += "";
if ((subcommand == "add")) {
global_retc = output_result(client_command(in, true));
}
if ((subcommand == "remove")) {
global_retc = output_result(client_command(disableu, true));
global_retc |= output_result(client_command(disableg, true));
}
return (0);
}
if (subcommand == "rm") {
XrdOucString in = "mgm.cmd=vid&mgm.subcmd=rm";
XrdOucString key = subtokenizer.GetTokenUnquoted();
if (key == "membership") {
key = subtokenizer.GetTokenUnquoted();
key.insert("vid:", 0);
XrdOucString key1 = key;
XrdOucString key2 = key;
XrdOucString in1 = in;
XrdOucString in2 = in;
key1 += ":uids";
key2 += ":gids";
in1 += "&mgm.vid.key=";
in1 += key1;
in2 += "&mgm.vid.key=";
in2 += key2;
global_retc = output_result(client_command(in1, true));
global_retc |= output_result(client_command(in2, true));
return (0);
}
if ((!key.length())) {
goto com_vid_usage;
}
if (key.beginswith("-h") || key.beginswith("--h")) {
goto com_vid_usage;
}
in += "&mgm.vid.key=";
in += key;
global_retc = output_result(client_command(in, true));
return (0);
}
com_vid_usage:
fprintf(stdout,
"usage: vid ls [-u] [-g] [-s] [-U] [-G] [-g] [-a] [-l] [-n] : list configured policies\n");
fprintf(stdout,
" -u : show only user role mappings\n");
fprintf(stdout,
" -g : show only group role mappings\n");
fprintf(stdout,
" -s : show list of sudoers\n");
fprintf(stdout,
" -U : show user alias mapping\n");
fprintf(stdout,
" -G : show group alias mapping\n");
fprintf(stdout,
" -y : show configured gateways\n");
fprintf(stdout,
" -a : show authentication\n");
fprintf(stdout,
" -N : show maximum anonymous (nobody) access level deepness - the tree deepness where unauthenticated access is possible (default is 1024)\n");
fprintf(stdout,
" -l : show geo location mapping\n");
fprintf(stdout,
" -n : show numerical ids instead of user/group names\n");
fprintf(stdout, "\n");
fprintf(stdout, " vid set membership -uids [,,...]\n");
fprintf(stdout, " vid set membership -gids [,,...]\n");
fprintf(stdout,
" vid rm membership : delete the membership entries for .\n");
fprintf(stdout, " vid set membership [+|-]sudo \n");
fprintf(stdout,
" vid set map -krb5|-gsi|-https|-sss|-unix|-tident|-voms|-grpc|-oauth2 [vuid:] [vgid:] \n");
fprintf(stdout,
" -voms : is : e.g. to map VOMS attribute /dteam/cern/Role=NULL/Capability=NULL one should define =/dteam/cern: \n");
fprintf(stdout,
" -sss key: : has to be defined on client side via 'export XrdSecsssENDORSEMENT='\n");
fprintf(stdout,
" -grpc key: : has to be added to the relevant GRPC request in the field 'authkey'\n");
fprintf(stdout,
" -https key: : has to be added to the relevant HTTP(S) request as a header 'x-gateway-authorization'\n");
fprintf(stdout,
" -oauth2 key: : describes the OAUTH resource endpoint to translate OAUTH tokens to user identities\n\n");
fprintf(stdout,
" vid set geotag : add to all IP's matching the prefix the geo location tag \n");
fprintf(stdout,
" N.B. specify the default assumption via 'vid set geotag default '\n");
fprintf(stdout,
" vid rm : remove configured vid with name key - hint: use config dump to see the key names of vid rules\n");
fprintf(stdout, "\n");
fprintf(stdout,
" vid enable|disable krb5|gsi|sss|unix|https|grpc|oauth2|ztn\n");
fprintf(stdout,
" : enable/disables the default mapping via password or external database\n");
fprintf(stdout, "\n");
fprintf(stdout,
" vid add|remove gateway [krb5|gsi|sss|unix|https|grpc]\n");
fprintf(stdout,
" : adds/removes a host as a (fuse) gateway with 'su' priviledges\n");
fprintf(stdout,
" [] restricts the gateway role change to the specified authentication method\n");
fprintf(stdout,
" vid publicaccesslevel \n");
fprintf(stdout,
" : sets the deepest directory level where anonymous access (nobody) is possible\n");
fprintf(stdout,
" vid tokensudo 0|1|2|3\n");
fprintf(stdout,
" : configure sudo policy when tokens are used\n");
fprintf(stdout,
" 0 : always allow token sudo (setting uid/gid from token) [default if not set]\n");
fprintf(stdout,
" 1 : allow token sudo if transport is encrypted\n");
fprintf(stdout,
" 2 : allow token sudo for strong authentication (not unix!)\n");
fprintf(stdout,
" 3 : never allow token sudo\n");
global_retc = EINVAL;
return (0);
}