in api/src/gmsa_service.cpp [799:980]
void Proceed( std::string krb_files_dir, CF_logger& cf_logger,
std::string aws_sm_secret_name )
{
if ( cookie.compare( CLASS_NAME_CallDataRenewKerberosArnLease ) != 0 )
{
return;
}
std::cerr << Util::getCurrentTime() << '\t' << "INFO: RenewKerberosArnLease " << 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 RequestHandleNonDomainJoinedKerberosLease 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_->RequestRenewKerberosArnLease( &add_krb_ctx_, &renew_krb_arn_request_,
&handle_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 CallDataRenewKerberosArnLease( service_, cq_ );
// The actual processing.
std::string accessId = renew_krb_arn_request_.access_key_id();
std::string secretKey = renew_krb_arn_request_.secret_access_key();
std::string sessionToken = renew_krb_arn_request_.session_token();
std::string region = renew_krb_arn_request_.region();
std::string username = "";
std::string password = "";
std::string err_msg;
if ( !accessId.empty() && !secretKey.empty() && !sessionToken.empty() &&
!region.empty() )
{
std::vector<std::string> metadatafiles =
get_meta_data_file_paths( krb_files_dir );
for ( auto file_path : metadatafiles )
{
krb_ticket_info_t* krb_ticket_info = new krb_ticket_info_t;
krb_ticket_arn_mapping_t* krb_ticket_arns = new krb_ticket_arn_mapping_t;
std::list<krb_ticket_info_t*> krb_ticket_info_list =
read_meta_data_json( file_path );
// refresh the kerberos tickets for the service accounts, if tickets ready
// for renewal
for ( auto krb_ticket : krb_ticket_info_list )
{
std::string credspec_info = krb_ticket->credspec_info;
if ( !credspec_info.empty() )
{
// get credentialspec contents:
Aws::Auth::AWSCredentials creds =
get_credentials( accessId, secretKey, sessionToken );
std::string response = retrieve_credspec_from_s3(
credspec_info, region, creds, false );
if ( response.empty() )
{
err_msg = "ERROR: credentialspec cannot be retrieved from s3";
std::cerr << Util::getCurrentTime() << '\t' << err_msg
<< std::endl;
break;
}
int parse_result = parse_cred_spec_domainless(
response, krb_ticket_info, krb_ticket_arns );
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 secretsArn =
krb_ticket_arns->credential_domainless_user_arn;
if ( secretsArn.empty() )
{
err_msg = "ERROR: invalid secrets manager arn";
std::cerr << Util::getCurrentTime() << '\t' << err_msg
<< std::endl;
break;
}
// retrieve domainless user credentials
std::tuple<std::string, std::string, std::string, std::string>
userCreds = retrieve_credspec_from_secrets_manager(
krb_ticket_arns->credential_domainless_user_arn, region,
creds );
username = std::get<0>( userCreds );
password = std::get<1>( userCreds );
std::string domain = std::get<2>( userCreds );
// std::string distinguished_name = std::get<3>( userCreds );
if ( isValidDomain( domain ) &&
!Util::contains_invalid_characters_in_ad_account_name(
username ) )
{
if ( !username.empty() && !password.empty() &&
!domain.empty() &&
username.length() < INPUT_CREDENTIALS_LENGTH &&
password.length() < INPUT_CREDENTIALS_LENGTH &&
domain.length() < DOMAIN_LENGTH )
{
std::string renewal_path = renew_gmsa_ticket(
krb_ticket, domain, username, password, cf_logger );
}
else
{
err_msg =
"ERROR: domainless AD user credentials is not "
"valid/ "
"credentials should not be more than 256 charaters";
std::cerr << Util::getCurrentTime() << '\t' << err_msg
<< std::endl;
break;
}
}
else
{
err_msg = "ERROR: invalid domainName/username";
std::cerr << Util::getCurrentTime() << '\t' << err_msg
<< std::endl;
break;
}
}
}
}
}
}
else
{
err_msg = "ERROR: invalid credentials/region";
std::cerr << Util::getCurrentTime() << '\t' << err_msg << std::endl;
}
secureClearString( username );
secureClearString( password );
secureClearString( accessId );
secureClearString( sessionToken );
secureClearString( secretKey );
// 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() )
{
renew_krb_arn_reply_.set_status( "failed" );
status_ = FINISH;
handle_krb_responder_.Finish(
renew_krb_arn_reply_, grpc::Status( grpc::StatusCode::INTERNAL, err_msg ),
this );
}
else
{
renew_krb_arn_reply_.set_status( "successful" );
status_ = FINISH;
handle_krb_responder_.Finish( renew_krb_arn_reply_, grpc::Status::OK, this );
}
}
else
{
GPR_ASSERT( status_ == FINISH );
// Once in the FINISH state, deallocate ourselves (CallData).
delete this;
}
return;
}