66// and limitations under the License.
77
88using System ;
9- using System . Collections . Generic ;
109using System . Reflection ;
1110using System . IO ;
1211using System . Linq ;
@@ -286,7 +285,8 @@ public Constants.Keystore GetDefaultKeystore()
286285 /// <param name="keyType">Combination of key algorithm and key size</param>
287286 /// <param name="keystore">Default keystore for the device</param>
288287 /// <param name="subject">Subject provided for the certificate</param>
289- public void CreateSelfSignedCert ( string alias , string keyType , string keystore , string subject )
288+ /// <param name="sans">Subject Alternative Names</param>
289+ public void CreateSelfSignedCert ( string alias , string keyType , string keystore , string subject , string [ ] sans )
290290 {
291291 try
292292 {
@@ -303,7 +303,7 @@ public void CreateSelfSignedCert(string alias, string keyType, string keystore,
303303 KeyType = keyType ,
304304 Keystore = keystore ,
305305 Subject = subject ,
306- SANS = [ ] ,
306+ SANS = sans ,
307307 ValidFrom = 0 , // Cert validity period will be determined by the template
308308 ValidTo = 0 // Cert validity period will be determined by the template
309309 }
@@ -347,45 +347,25 @@ public void CreateSelfSignedCert(string alias, string keyType, string keystore,
347347 }
348348
349349 /// <summary>
350- /// Obtains a CSR for the self-signed or existing certificate with private key on the device.
351- /// Fields from the certificate will be copied into the CSR.
352- /// SANs will be added to the CSR.
350+ /// Obtains a CSR for the self-signed certificate with private key on the device.
351+ /// Fields from the self-signed certificate will be copied into the CSR.
353352 /// </summary>
354353 /// <param name="alias">Unique identifier for the cert to be generated from the CSR</param>
355- /// <param name="subject">Subject provided for the certificate</param>
356- /// <param name="sans">Subject Alternative Names</param>
357354 /// <returns>CSR string</returns>
358- public string ObtainCSR ( string alias , string subject , List < string > sans )
355+ public string ObtainCSR ( string alias )
359356 {
360357 try
361358 {
362359 Logger . MethodEntry ( ) ;
363360
364361 var postCSRResource = $ "{ Constants . RestApiEntryPoint } /certificates/{ alias } /get_csr";
365362
366- // Compose the body --- This is required.
367- // All information obtained in the self-signed or existing cert will be used to create the CSR.
363+ // Compose the body --- This is required, but leaving the contents blank .
364+ // All information obtained in the self-signed cert will be used to create the CSR.
368365 // If there are attributes assigned by the CA, those will override the attributes that end up
369366 // in the certificate signed by the CA.
370- // 1. If a field is filled out, that value will be used in the CSR
371- // 2. If a field is NOT filled out, the existing value from the existing certificate will be copied into the CSR
372- // 3. If a field is filled out with a blank value, that field is not copied from the existing certificate nor added to the CSR
373- var jsonBody = new StringBuilder ( @"{""data"":{" ) ;
374-
375- if ( sans . Count == 0 )
376- {
377- jsonBody . Append ( @"""subject"":""" ) . Append ( subject ) . Append ( "}}" ) ;
378- }
379- else
380- {
381- jsonBody . Append ( @"""subject"":""" ) . Append ( subject ) . Append ( @""",""subject_alt_names"": [" ) ;
382- string result = string . Join ( "," , sans ) ;
383- jsonBody . Append ( result ) . Append ( "]}}" ) ;
384- }
385-
386- Logger . LogDebug ( $ "POST Request Body: { jsonBody } ") ;
387-
388- var httpResponse = ExecuteHttp ( postCSRResource , Method . Post , Constants . ApiType . Rest , jsonBody . ToString ( ) ) ;
367+ string jsonBody = @"{""data"":{}}" ;
368+ var httpResponse = ExecuteHttp ( postCSRResource , Method . Post , Constants . ApiType . Rest , jsonBody ) ;
389369
390370 // Decode the HTTP response if failed
391371 if ( httpResponse is { IsSuccessful : false } )
@@ -544,30 +524,83 @@ public void RemoveCACertificate(string alias)
544524 Logger . LogError ( $ "HTTP Request unsuccessful - HTTP Response: { DecodeHttpStatus ( httpResponse ) } ") ;
545525 throw new Exception ( $ "HTTP Request unsuccessful.") ;
546526 }
527+
547528 // Decode the API response when HTTP response is successful
529+ if ( httpResponse != null && string . IsNullOrEmpty ( httpResponse . Content ) )
530+ {
531+ throw new Exception ( "No content returned from HTTP Response" ) ;
532+ }
533+
534+ RestApiResponse apiResponse = JsonConvert . DeserializeObject < RestApiResponse > ( httpResponse . Content ) ;
535+ if ( apiResponse . Status == Constants . Status . Success )
536+ {
537+ Logger . MethodExit ( ) ;
538+ }
548539 else
549540 {
550- if ( httpResponse != null && string . IsNullOrEmpty ( httpResponse . Content ) )
551- {
552- throw new Exception ( "No content returned from HTTP Response" ) ;
553- }
541+ ErrorData error = JsonConvert . DeserializeObject < ErrorData > ( httpResponse . Content ) ;
542+ throw new Exception (
543+ $ "API error encountered - { error . ErrorInfo . Message } - (Code: { error . ErrorInfo . Code } )") ;
544+ }
545+ }
546+ catch ( Exception e )
547+ {
548+ Logger . LogError ( "Error completing CA certificate remove: " + LogHandler . FlattenException ( e ) ) ;
549+ throw new Exception ( e . Message ) ;
550+ }
551+ }
552+
553+ /// <summary>
554+ /// Removes a certificate with private key from the device.
555+ /// </summary>
556+ /// <param name="alias">Unique identifier of the CA certificate to be removed</param>
557+ public void RemoveCertificate ( string alias )
558+ {
559+ try
560+ {
561+ Logger . MethodEntry ( ) ;
554562
555- RestApiResponse apiResponse = JsonConvert . DeserializeObject < RestApiResponse > ( httpResponse . Content ) ;
556- if ( apiResponse . Status == Constants . Status . Success )
563+ var deleteCertResource = $ "{ Constants . RestApiEntryPoint } /certificates/{ alias } ";
564+ var httpResponse = ExecuteHttp ( deleteCertResource , Method . Delete ) ;
565+
566+ // Decode the HTTP response if failed
567+ if ( httpResponse is { IsSuccessful : false } )
568+ {
569+ Logger . LogError ( $ "HTTP Request unsuccessful - HTTP Response: { DecodeHttpStatus ( httpResponse ) } ") ;
570+ throw new Exception ( $ "HTTP Request unsuccessful.") ;
571+ }
572+
573+ // Decode the API response when HTTP response is successful
574+ if ( httpResponse != null && string . IsNullOrEmpty ( httpResponse . Content ) )
575+ {
576+ throw new Exception ( "No content returned from HTTP Response" ) ;
577+ }
578+
579+ RestApiResponse apiResponse = JsonConvert . DeserializeObject < RestApiResponse > ( httpResponse . Content ) ;
580+ if ( apiResponse . Status == Constants . Status . Success )
581+ {
582+ Logger . MethodExit ( ) ;
583+ }
584+ else
585+ {
586+ ErrorData error = JsonConvert . DeserializeObject < ErrorData > ( httpResponse . Content ) ;
587+
588+ // Check for error code 5 - "Validation error: Certificate is in use" or "Validation error: Certificate is not deletable" ---
589+ // This will capture all device ID certs, which we do not want to delete anyway
590+ if ( error . ErrorInfo is { Code : 5 , Message : "Validation error: Certificate is not deletable" or "Validation error: Certificate is in use" } )
557591 {
558- Logger . MethodExit ( ) ;
592+ Logger . LogWarning ( $ "API warning encountered - { error . ErrorInfo . Message } - (Code: { error . ErrorInfo . Code } )" ) ;
559593 }
560594 else
561595 {
562- ErrorData error = JsonConvert . DeserializeObject < ErrorData > ( httpResponse . Content ) ;
563596 throw new Exception (
564597 $ "API error encountered - { error . ErrorInfo . Message } - (Code: { error . ErrorInfo . Code } )") ;
565598 }
566599 }
567600 }
568601 catch ( Exception e )
569602 {
570- Logger . LogError ( "Error completing CA certificate remove: " + LogHandler . FlattenException ( e ) ) ;
603+ Logger . LogError ( "Error completing certificate remove: " + LogHandler . FlattenException ( e ) ) ;
571604 throw new Exception ( e . Message ) ;
572605 }
573606 }
0 commit comments