in api/src/gmsa_service.cpp [1084:1261]
void Proceed( std::string krb_files_dir, CF_logger& cf_logger,
std::string aws_sm_secret_name )
{
if ( cookie.compare( CLASS_NAME_CallDataCreateKerberosLease ) != 0 )
{
return;
}
std::cerr << Util::getCurrentTime() << '\t' << "INFO: CallDataCreateKerberosLease "
<< this << "status: " << status_ << std::endl;
if ( status_ == CREATE )
{
// Make this instance progress to the PROCESS state.
status_ = PROCESS;
// As part of the initial CREATE state, we *request* that the system
// start processing RequestAddKerberosLease requests. In this request, "this" acts
// are the tag uniquely identifying the request (so that different CallData
// instances can serve different requests concurrently), in this case
// the memory address of this CallData instance.
service_->RequestAddKerberosLease( &add_krb_ctx_, &create_krb_request_,
&create_krb_responder_, cq_, cq_, this );
}
else if ( status_ == PROCESS )
{
// Spawn a new CallData instance to serve new clients while we process
// the one for this CallData. The instance will deallocate itself as
// part of its FINISH state.
new CallDataCreateKerberosLease( service_, cq_ );
// The actual processing.
std::string lease_id = generate_lease_id();
std::list<krb_ticket_info_t*> krb_ticket_info_list;
std::unordered_set<std::string> krb_ticket_dirs;
std::string err_msg;
std::string log_message;
create_krb_reply_.set_lease_id( lease_id );
for ( int i = 0; i < create_krb_request_.credspec_contents_size(); i++ )
{
krb_ticket_info_t* krb_ticket_info = new krb_ticket_info_t;
int parse_result = parse_cred_spec( create_krb_request_.credspec_contents( i ),
krb_ticket_info );
if ( parse_result != 0 )
{
err_msg = "ERROR: invalid credentialspec fields";
std::cerr << Util::getCurrentTime() << '\t' << err_msg << std::endl;
break;
}
// only add the ticket info if the parsing is successful
if ( parse_result == 0 )
{
std::string krb_files_path = krb_files_dir + "/" + lease_id + "/" +
krb_ticket_info->service_account_name;
krb_ticket_info->krb_file_path = krb_files_path;
krb_ticket_info->domainless_user = "";
// handle duplicate service accounts
if ( !krb_ticket_dirs.count( krb_files_path ) )
{
krb_ticket_dirs.insert( krb_files_path );
krb_ticket_info_list.push_back( krb_ticket_info );
}
}
else
{
err_msg = "Error: credential spec provided is not properly formatted";
std::cerr << Util::getCurrentTime() << '\t' << err_msg << std::endl;
break;
}
}
if ( err_msg.empty() )
{
// create the kerberos tickets for the service accounts
for ( auto krb_ticket : krb_ticket_info_list )
{
// invoke to get machine ticket
std::pair<int, std::string> status;
if ( aws_sm_secret_name.length() != 0 )
{
status = Util::generate_krb_ticket_using_secret_vault(
krb_ticket->domain_name, aws_sm_secret_name, cf_logger );
krb_ticket->domainless_user =
"awsdomainlessusersecret:" + aws_sm_secret_name;
}
else
{
status = generate_krb_ticket_from_machine_keytab(
krb_ticket->domain_name, cf_logger );
}
if ( status.first < 0 )
{
log_message = "Error: " + std::to_string( status.first ) +
" Cannot get machine krb ticket " + status.second;
cf_logger.logger( LOG_ERR, log_message.c_str() );
err_msg = "ERROR: cannot get machine krb ticket";
std::cerr << Util::getCurrentTime() << '\t' << err_msg << std::endl;
break;
}
std::string krb_file_path = krb_ticket->krb_file_path;
if ( std::filesystem::exists( krb_file_path ) )
{
log_message = "Directory already exists: " + krb_file_path;
cf_logger.logger( LOG_INFO, log_message.c_str() );
break;
}
std::filesystem::create_directories( krb_file_path );
std::string krb_ccname_str = krb_ticket->krb_file_path + "/krb5cc";
if ( !std::filesystem::exists( krb_ccname_str ) )
{
std::ofstream file( krb_ccname_str );
file.close();
krb_ticket->krb_file_path = krb_ccname_str;
}
std::pair<int, std::string> gmsa_ticket_result =
fetch_gmsa_password_and_create_krb_ticket(
krb_ticket->domain_name, krb_ticket, krb_ccname_str, cf_logger );
if ( gmsa_ticket_result.first != 0 )
{
err_msg = "ERROR: Cannot get gMSA krb ticket";
std::cerr << Util::getCurrentTime() << '\t' << err_msg << std::endl;
log_message = "ERROR: Cannot get gMSA krb ticket " +
std::to_string( status.first ) + " " + status.second;
cf_logger.logger( LOG_ERR, log_message.c_str() );
break;
}
else
{
log_message = "gMSA ticket is at " + gmsa_ticket_result.second;
cf_logger.logger( LOG_INFO, log_message.c_str() );
std::cerr << Util::getCurrentTime() << '\t'
<< "INFO: gMSA ticket is at " << gmsa_ticket_result.second
<< std::endl;
}
create_krb_reply_.add_created_kerberos_file_paths( krb_file_path );
}
}
// And we are done! Let the gRPC runtime know we've finished, using the
// memory address of this instance as the uniquely identifying tag for
// the event.
if ( !err_msg.empty() )
{
// remove the directories on failure
for ( auto krb_ticket : krb_ticket_info_list )
{
std::filesystem::remove_all( krb_ticket->krb_file_path );
}
status_ = FINISH;
create_krb_responder_.Finish(
create_krb_reply_, grpc::Status( grpc::StatusCode::INTERNAL, err_msg ),
this );
}
else
{
// write the ticket information to meta data file
write_meta_data_json( krb_ticket_info_list, lease_id, krb_files_dir );
status_ = FINISH;
create_krb_responder_.Finish( create_krb_reply_, grpc::Status::OK, this );
}
}
else
{
GPR_ASSERT( status_ == FINISH );
// Once in the FINISH state, deallocate ourselves (CallData).
delete this;
}
return;
}