@@ -34,6 +34,7 @@ pub enum AdminBackend {
34
34
generate_sam_account_name : Option < ActiveDirectorySamAccountNameRules > ,
35
35
} ,
36
36
}
37
+
37
38
#[ derive( Serialize , Deserialize , Debug ) ]
38
39
pub struct ActiveDirectorySamAccountNameRules {
39
40
pub prefix : String ,
@@ -71,25 +72,65 @@ pub async fn provision_keytab(krb5_config_path: &Path, req: &Request) -> Result<
71
72
let req_str = serde_json:: to_vec ( & req) . context ( SerializeRequestSnafu ) ?;
72
73
73
74
let mut child = Command :: new ( "stackable-krb5-provision-keytab" )
75
+ // make sure the process is killed if we error out of this fn somewhere due to
76
+ // an error when writing to stdin or getting stdout
77
+ // Usually we'd expect the process to terminate on its own, this is a fail safe to ensure
78
+ // it gets killed in case it hangs for some reason.
74
79
. kill_on_drop ( true )
75
80
. env ( "KRB5_CONFIG" , krb5_config_path)
76
81
// ldap3 uses the default client keytab to authenticate to the LDAP server
77
82
. env ( "KRB5_CLIENT_KTNAME" , & req. admin_keytab_path )
78
- // avoid leaking credentials between secret volumes/secretclasses
83
+ // avoid leaking credentials between secret volumes/secretclasses by only storing the
84
+ // TGT that is obtained for the operation in the memory of the short lives process
85
+ // spawned by `Command::new` above - this way it'll be wiped from memory once this exits
86
+ // With any shared or persistent ticket cache this might stick around and potentially be
87
+ // reused by other volumes (which could cause privilege escalations and similar fun issues)
79
88
. env ( "KRB5CCNAME" , "MEMORY:" )
80
89
. stdin ( Stdio :: piped ( ) )
81
90
. stdout ( Stdio :: piped ( ) )
82
91
. spawn ( )
83
92
. context ( SpawnProvisionerSnafu ) ?;
84
- let mut stdin = child. stdin . take ( ) . unwrap ( ) ;
93
+
94
+ // Get a `ChildStdin` object for the spawned process and write the serialized request
95
+ // for a Principal into it in order for the child process to deserialize it and
96
+ // process the request
97
+ let mut stdin = child
98
+ . stdin
99
+ . take ( )
100
+ // a failure here has some fundamental reason like us taking ownership of the pipe
101
+ // earlier, which is most probably more a coding than a runtime error - this is
102
+ // why this error is not handled here, but we panic instead
103
+ . expect (
104
+ "Failed to take ownership of stdin pipe of stackable-krb5-provision-keytab command! " ,
105
+ ) ;
85
106
stdin. write_all ( & req_str) . await . context ( WriteRequestSnafu ) ?;
86
107
stdin. flush ( ) . await . context ( WriteRequestSnafu ) ?;
87
108
drop ( stdin) ;
109
+
110
+ // Wait for the process to finish and capture output
111
+ // This will always return Ok(...) regardless of exit code or output of the child process
112
+ // Failure here means that something went wrong with connecting to the process or obtaining
113
+ // exit code or output
88
114
let output = child
89
115
. wait_with_output ( )
90
116
. await
91
117
. context ( WaitProvisionerSnafu ) ?;
92
- serde_json:: from_slice :: < Result < Response , String > > ( & output. stdout )
93
- . context ( DeserializeResponseSnafu ) ?
94
- . map_err ( |msg| Error :: RunProvisioner { msg } )
118
+
119
+ // Check if the spawned command returned 0 as return code
120
+ if output. status . success ( ) {
121
+ // Check for success of the operation by deserializing stdout of the process to a `Response`
122
+ // struct - since `Response` is an empty struct with no fields this effectively means that
123
+ // any output will fail to deserialize and cause an `Error::RunProvisioner` to be propagated
124
+ // with the output of the child process
125
+ serde_json:: from_slice :: < Result < Response , String > > ( & output. stdout )
126
+ . context ( DeserializeResponseSnafu ) ?
127
+ . map_err ( |msg| Error :: RunProvisioner { msg } )
128
+ } else {
129
+ Err ( Error :: RunProvisioner {
130
+ msg : format ! (
131
+ "Got non zero return code from stackable-krb5-provision-keytab: [{:?}]" ,
132
+ output. status. code( )
133
+ ) ,
134
+ } )
135
+ }
95
136
}
0 commit comments