@@ -71,24 +71,44 @@ pub async fn provision_keytab(krb5_config_path: &Path, req: &Request) -> Result<
71
71
let req_str = serde_json:: to_vec ( & req) . context ( SerializeRequestSnafu ) ?;
72
72
73
73
let mut child = Command :: new ( "stackable-krb5-provision-keytab" )
74
+ // make sure the process is killed if we error out of this fn somewhere due to
75
+ // an error when writing to stdin or getting stdout
74
76
. kill_on_drop ( true )
75
77
. env ( "KRB5_CONFIG" , krb5_config_path)
76
78
// ldap3 uses the default client keytab to authenticate to the LDAP server
77
79
. env ( "KRB5_CLIENT_KTNAME" , & req. admin_keytab_path )
78
- // avoid leaking credentials between secret volumes/secretclasses
80
+ // avoid leaking credentials between secret volumes/secretclasses by only storing the
81
+ // TGT that is obtained for the operation in the memory of the short lives process
82
+ // spawned by `Command::new` above - this way it'll be wiped from memory once this exits
83
+ // With any shared or persistent ticket cache this might stick around and potentially be
84
+ // reused by later runs
79
85
. env ( "KRB5CCNAME" , "MEMORY:" )
80
86
. stdin ( Stdio :: piped ( ) )
81
87
. stdout ( Stdio :: piped ( ) )
82
88
. spawn ( )
83
89
. context ( SpawnProvisionerSnafu ) ?;
90
+
91
+ // Get a `ChildStdin` object for the spawned process and write the serialized request
92
+ // for a Principal into it in order for the child process to deserialize it and
93
+ // process the request
84
94
let mut stdin = child. stdin . take ( ) . unwrap ( ) ;
85
95
stdin. write_all ( & req_str) . await . context ( WriteRequestSnafu ) ?;
86
96
stdin. flush ( ) . await . context ( WriteRequestSnafu ) ?;
87
97
drop ( stdin) ;
98
+
99
+ // Wait for the process to finish and capture output
100
+ // This will always return Ok(...) regardless of exit code or output of the child process
101
+ // Failure here means that something went wrong with connecting to the process or obtaining
102
+ // exit code or output
88
103
let output = child
89
104
. wait_with_output ( )
90
105
. await
91
106
. context ( WaitProvisionerSnafu ) ?;
107
+
108
+ // Check for success of the operation by deserializing stdout of the process to a `Response`
109
+ // struct - since `Response` is an empty struct with no fields this effectively means that
110
+ // any output will fail to deserialize and cause an `Error::RunProvisioner` to be propagated
111
+ // with the output of the child process
92
112
serde_json:: from_slice :: < Result < Response , String > > ( & output. stdout )
93
113
. context ( DeserializeResponseSnafu ) ?
94
114
. map_err ( |msg| Error :: RunProvisioner { msg } )
0 commit comments