diff --git a/db/pf-schema-X.Y.sql b/db/pf-schema-X.Y.sql
index 83e8cb019c38..ee693b90dd9c 100644
--- a/db/pf-schema-X.Y.sql
+++ b/db/pf-schema-X.Y.sql
@@ -1619,6 +1619,33 @@ CREATE FUNCTION ROUND_TO_MONTH (d DATETIME)
RETURNS DATETIME DETERMINISTIC
RETURN DATE_ADD(DATE(d),interval -DAY(d)+1 DAY);
+
+--
+-- Create table node_tls
+--
+
+CREATE TABLE node_tls (
+ `mac` varchar(17) NOT NULL PRIMARY KEY,
+ `TLSCertSerial` varchar(255) default NULL,
+ `TLSCertExpiration` varchar(255) default NULL,
+ `TLSCertValidSince` varchar(255) default NULL,
+ `TLSCertSubject` varchar(255) default NULL,
+ `TLSCertIssuer` varchar(255) default NULL,
+ `TLSCertCommonName` varchar(255) default NULL,
+ `TLSCertSubjectAltNameEmail` varchar(255) default NULL,
+ `TLSClientCertSerial` varchar(255) default NULL,
+ `TLSClientCertExpiration` varchar(255) default NULL,
+ `TLSClientCertValidSince` varchar(255) default NULL,
+ `TLSClientCertSubject` varchar(255) default NULL,
+ `TLSClientCertIssuer` varchar(255) default NULL,
+ `TLSClientCertCommonName` varchar(255) default NULL,
+ `TLSClientCertSubjectAltNameEmail` varchar(255) default NULL,
+ `TLSClientCertX509v3ExtendedKeyUsage` varchar(255) default NULL,
+ `TLSClientCertX509v3SubjectKeyIdentifier` varchar(255) default NULL,
+ `TLSClientCertX509v3AuthorityKeyIdentifier` varchar(255) default NULL,
+ `TLSClientCertX509v3ExtendedKeyUsageOID` varchar(255) default NULL
+) ENGINE=InnoDB DEFAULT CHARACTER SET = 'utf8mb4' COLLATE = 'utf8mb4_general_ci';
+
--
-- Updating to current version
--
diff --git a/db/upgrade-X.X-X.Y.sql b/db/upgrade-X.X-X.Y.sql
index 69582502bfaa..1f1f57f6bed9 100644
--- a/db/upgrade-X.X-X.Y.sql
+++ b/db/upgrade-X.X-X.Y.sql
@@ -70,6 +70,30 @@ ALTER TABLE radius_audit_log MODIFY created_at TIMESTAMP NOT NULL DEFAULT CURREN
\! echo "Make psk unique";
ALTER TABLE person ADD CONSTRAINT UNIQUE person_psk (`psk`);
+\! echo "Create table node_tls"
+
+CREATE TABLE IF NOT EXISTS node_tls (
+ `mac` varchar(17) NOT NULL PRIMARY KEY,
+ `TLSCertSerial` varchar(255) default NULL,
+ `TLSCertExpiration` varchar(255) default NULL,
+ `TLSCertValidSince` varchar(255) default NULL,
+ `TLSCertSubject` varchar(255) default NULL,
+ `TLSCertIssuer` varchar(255) default NULL,
+ `TLSCertCommonName` varchar(255) default NULL,
+ `TLSCertSubjectAltNameEmail` varchar(255) default NULL,
+ `TLSClientCertSerial` varchar(255) default NULL,
+ `TLSClientCertExpiration` varchar(255) default NULL,
+ `TLSClientCertValidSince` varchar(255) default NULL,
+ `TLSClientCertSubject` varchar(255) default NULL,
+ `TLSClientCertIssuer` varchar(255) default NULL,
+ `TLSClientCertCommonName` varchar(255) default NULL,
+ `TLSClientCertSubjectAltNameEmail` varchar(255) default NULL,
+ `TLSClientCertX509v3ExtendedKeyUsage` varchar(255) default NULL,
+ `TLSClientCertX509v3SubjectKeyIdentifier` varchar(255) default NULL,
+ `TLSClientCertX509v3AuthorityKeyIdentifier` varchar(255) default NULL,
+ `TLSClientCertX509v3ExtendedKeyUsageOID` varchar(255) default NULL
+) ENGINE=InnoDB DEFAULT CHARACTER SET = 'utf8mb4' COLLATE = 'utf8mb4_general_ci';
+
\! echo "Incrementing PacketFence schema version...";
INSERT IGNORE INTO pf_version (id, version, created_at) VALUES (@VERSION_INT, CONCAT_WS('.', @MAJOR_VERSION, @MINOR_VERSION), NOW());
diff --git a/go/cron/flush_radius_audit_log_job.go b/go/cron/flush_radius_audit_log_job.go
index f4828cacf075..df15d1355b7e 100644
--- a/go/cron/flush_radius_audit_log_job.go
+++ b/go/cron/flush_radius_audit_log_job.go
@@ -71,11 +71,11 @@ func (j *FlushRadiusAuditLogJob) Run() {
log.LogError(ctx, fmt.Sprintf("%s error running: %s", j.Name(), err.Error()))
continue
}
-
jsonStr = string(s)
}
-
+ jsonStr = strings.Replace(jsonStr, "\\", "", -1)
err := json.Unmarshal([]byte(jsonStr), &entry)
+
if err != nil {
log.LogError(ctx, fmt.Sprintf("%s error running: %s", j.Name(), err.Error()))
continue
@@ -121,11 +121,33 @@ func (j *FlushRadiusAuditLogJob) flushLogs(entries [][]interface{}) error {
return err
}
+ // REPLACE in node_tls
+ sqlTLS, argsTLS, err := j.buildQueryTLS(entries)
+ if err != nil {
+ return err
+ }
+
+ res, err = db.ExecContext(
+ ctx,
+ sqlTLS,
+ argsTLS...,
+ )
+
+ if err != nil {
+ return err
+ }
+
+ _, err = res.RowsAffected()
+ if err != nil {
+ return err
+ }
+
log.LogInfo(ctx, fmt.Sprintf("Flushed %d radius_audit_log", rows))
return nil
}
const RADIUS_AUDIT_LOG_COLUMN_COUNT = 37
+const NODE_TLS_COLUMN_COUNT = 19
/*
query = "INSERT INTO radius_audit_log \
@@ -232,6 +254,79 @@ func (j *FlushRadiusAuditLogJob) argsFromEntry(entry []interface{}) []interface{
return args
}
+func (j *FlushRadiusAuditLogJob) buildQueryTLS(entries [][]interface{}) (string, []interface{}, error) {
+ sql := `
+INSERT INTO node_tls
+ (
+ mac, TLSCertSerial, TLSCertExpiration, TLSCertValidSince,
+ TLSCertSubject, TLSCertIssuer, TLSCertCommonName,
+ TLSCertSubjectAltNameEmail, TLSClientCertSerial,
+ TLSClientCertExpiration, TLSClientCertValidSince,
+ TLSClientCertSubject, TLSClientCertIssuer,
+ TLSClientCertCommonName, TLSClientCertSubjectAltNameEmail,
+ TLSClientCertX509v3ExtendedKeyUsage,
+ TLSClientCertX509v3SubjectKeyIdentifier,
+ TLSClientCertX509v3AuthorityKeyIdentifier,
+ TLSClientCertX509v3ExtendedKeyUsageOID
+ )
+VALUES `
+ bind := "( ?" + strings.Repeat(",?", NODE_TLS_COLUMN_COUNT-1) + ")"
+ sql += bind + strings.Repeat(","+bind, len(entries)-1)
+ sql += `
+ ON DUPLICATE KEY UPDATE TLSCertSerial = VALUES(TLSCertSerial),
+ TLSCertExpiration = VALUES(TLSCertExpiration), TLSCertValidSince = VALUES(TLSCertValidSince),
+ TLSCertSubject = VALUES(TLSCertSubject), TLSCertIssuer = VALUES(TLSCertIssuer), TLSCertCommonName = VALUES( TLSCertCommonName),
+ TLSCertSubjectAltNameEmail = VALUES(TLSCertSubjectAltNameEmail), TLSClientCertSerial = VALUES(TLSClientCertSerial),
+ TLSClientCertExpiration = VALUES(TLSClientCertExpiration), TLSClientCertValidSince = VALUES(TLSClientCertValidSince),
+ TLSClientCertSubject = VALUES(TLSClientCertSubject), TLSClientCertIssuer = VALUES(TLSClientCertIssuer),
+ TLSClientCertCommonName = VALUES(TLSClientCertCommonName), TLSClientCertSubjectAltNameEmail = VALUES(TLSClientCertSubjectAltNameEmail),
+ TLSClientCertX509v3ExtendedKeyUsage = VALUES(TLSClientCertX509v3ExtendedKeyUsage),
+ TLSClientCertX509v3SubjectKeyIdentifier = VALUES(TLSClientCertX509v3SubjectKeyIdentifier),
+ TLSClientCertX509v3AuthorityKeyIdentifier = VALUES(TLSClientCertX509v3AuthorityKeyIdentifier),
+ TLSClientCertX509v3ExtendedKeyUsageOID = VALUES(TLSClientCertX509v3ExtendedKeyUsageOID)
+
+ `
+ args := make([]interface{}, 0, NODE_TLS_COLUMN_COUNT)
+ for _, e := range entries {
+ if keyExists(e[1].(map[string]interface{}), "Calling-Station-Id") && keyExists(e[1].(map[string]interface{}), "TLS-Client-Cert-Common-Name") {
+ args = append(args, j.argsFromEntryForTLS(e)...)
+ }
+ }
+ return sql, args, nil
+}
+
+func keyExists(myMap map[string]interface{}, key string) bool {
+ _, exists := myMap[key]
+ return exists
+}
+
+func (j *FlushRadiusAuditLogJob) argsFromEntryForTLS(entry []interface{}) []interface{} {
+ args := make([]interface{}, NODE_TLS_COLUMN_COUNT)
+ var request map[string]interface{}
+ request = entry[1].(map[string]interface{})
+ request = parseRequestArgs(request)
+ args[0] = formatRequestValue(request["Calling-Station-Id"], "")
+ args[1] = formatRequestValue(request["TLS-Cert-Serial"], "N/A")
+ args[2] = formatRequestValue(request["TLS-Cert-Expiration"], "N/A")
+ args[3] = formatRequestValue(request["TLS-Cert-Valid-Since"], "N/A")
+ args[4] = formatRequestValue(request["TLS-Cert-Subject"], "N/A")
+ args[5] = formatRequestValue(request["TLS-Cert-Issuer"], "N/A")
+ args[6] = formatRequestValue(request["TLS-Cert-Common-Name"], "N/A")
+ args[7] = formatRequestValue(request["TLS-Cert-Subject-Alt-Name-Email"], "N/A")
+ args[8] = formatRequestValue(request["TLS-Client-Cert-Serial"], "N/A")
+ args[9] = formatRequestValue(request["TLS-Client-Cert-Expiration"], "N/A")
+ args[10] = formatRequestValue(request["TLS-Client-Cert-Valid-Since"], "N/A")
+ args[11] = formatRequestValue(request["TLS-Client-Cert-Subject"], "N/A")
+ args[12] = formatRequestValue(request["TLS-Client-Cert-Issuer"], "N/A")
+ args[13] = formatRequestValue(request["TLS-Client-Cert-Common-Name"], "N/A")
+ args[14] = formatRequestValue(request["TLS-Client-Cert-Subject-Alt-Name-Email"], "N/A")
+ args[15] = formatRequestValue(request["TLS-Client-Cert-X509v3-Extended-Key-Usage"], "N/A")
+ args[16] = formatRequestValue(request["TLS-Client-Cert-X509v3-Subject-Key-Identifier"], "N/A")
+ args[17] = formatRequestValue(request["TLS-Client-Cert-X509v3-Authority-Key-Identifier"], "N/A")
+ args[18] = formatRequestValue(request["TLS-Client-Cert-X509v3-Extended-Key-Usage-OID"], "N/A")
+ return args
+}
+
func formatRequest(request map[string]interface{}) string {
parts := []string{}
keys := util.MapKeys(request)
@@ -312,7 +407,6 @@ func escapeRadiusRequest(s string) string {
if size == len(s) {
return s
}
-
out := make([]byte, size)
j := 0
for _, c := range []byte(s) {
@@ -370,114 +464,114 @@ func parseRequestArgs(request map[string]interface{}) map[string]interface{} {
type AKMSuite int
const (
- AKMReserved AKMSuite = iota // 0 - Reserved
- IEEE8021X // 1 - 802.1X
- PSK // 2 - PSK
- FT_8021X // 3 - FT over 802.1X
- FT_PSK // 4 - FT over PSK
- WPA_8021X // 5 - WPA with 802.1X
- WPA_PSK // 6 - WPA with PSK
- OWE // 7 - OWE
- OWE_Transition // 8 - OWE Transition Mode
- SAE // 9 - Simultaneous Authentication of Equals
- FT_SAE // 10 - FT over SAE
- FILS_SHA256 // 11 - FILS-SHA256
- FILS_SHA384 // 12 - FILS-SHA384
- FT_FILS_SHA256 // 13 - FT over FILS-SHA256
- FT_FILS_SHA384 // 14 - FT over FILS-SHA384
- OWE_transition_mode // 15 - OWE transition mode
+ AKMReserved AKMSuite = iota // 0 - Reserved
+ IEEE8021X // 1 - 802.1X
+ PSK // 2 - PSK
+ FT_8021X // 3 - FT over 802.1X
+ FT_PSK // 4 - FT over PSK
+ WPA_8021X // 5 - WPA with 802.1X
+ WPA_PSK // 6 - WPA with PSK
+ OWE // 7 - OWE
+ OWE_Transition // 8 - OWE Transition Mode
+ SAE // 9 - Simultaneous Authentication of Equals
+ FT_SAE // 10 - FT over SAE
+ FILS_SHA256 // 11 - FILS-SHA256
+ FILS_SHA384 // 12 - FILS-SHA384
+ FT_FILS_SHA256 // 13 - FT over FILS-SHA256
+ FT_FILS_SHA384 // 14 - FT over FILS-SHA384
+ OWE_transition_mode // 15 - OWE transition mode
)
type CipherSuite int
const (
- CipherReserved CipherSuite = iota // 0 - Reserved
- WEP40 // 1 - WEP-40
- TKIP // 2 - TKIP
- CipherReserved3 // 3 - Reserved
- CCMP128 // 4 - CCMP-128
- WEP104 // 5 - WEP-104
- BIPCMAC128 // 6 - BIP-CMAC-128
- GCMP128 // 7 - GCMP-128
- GCMP256 // 8 - GCMP-256
- CCMP256 // 9 - CCMP-256
- BIPGMAC128 // 10 - BIP-GMAC-128
- BIPGMAC256 // 11 - BIP-GMAC-256
- SMS4 // 12 - SMS4
- CKIP128 // 13 - CKIP-128
- CKIP128_PMK // 14 - CKIP-128 with PMK caching
- CipherReserved15 // 15 - Reserved
+ CipherReserved CipherSuite = iota // 0 - Reserved
+ WEP40 // 1 - WEP-40
+ TKIP // 2 - TKIP
+ CipherReserved3 // 3 - Reserved
+ CCMP128 // 4 - CCMP-128
+ WEP104 // 5 - WEP-104
+ BIPCMAC128 // 6 - BIP-CMAC-128
+ GCMP128 // 7 - GCMP-128
+ GCMP256 // 8 - GCMP-256
+ CCMP256 // 9 - CCMP-256
+ BIPGMAC128 // 10 - BIP-GMAC-128
+ BIPGMAC256 // 11 - BIP-GMAC-256
+ SMS4 // 12 - SMS4
+ CKIP128 // 13 - CKIP-128
+ CKIP128_PMK // 14 - CKIP-128 with PMK caching
+ CipherReserved15 // 15 - Reserved
)
-func(c CipherSuite) String() string {
+func (c CipherSuite) String() string {
switch c {
- case WEP40:
- return "WEP-40"
- case TKIP:
- return "TKIP"
- case CCMP128:
- return "CCMP-128"
- case WEP104:
- return "WEP-104"
- case GCMP128:
- return "GCMP-128"
- case GCMP256:
- return "GCMP-256"
- case CCMP256:
- return "CCMP-256"
- case BIPCMAC128:
- return "BIP-CMAC-128"
- case BIPGMAC128:
- return "BIP-GMAC-128"
- case BIPGMAC256:
- return "BIP-GMAC-256"
- case SMS4:
- return "SMS4"
- case CKIP128:
- return "CKIP-128"
- case CKIP128_PMK:
- return "CKIP-128 with PMK caching"
- case CipherReserved3, CipherReserved15:
- return "Reserved"
- default:
- return fmt.Sprintf("Unknown cipher suite (Value: %d)", c)
+ case WEP40:
+ return "WEP-40"
+ case TKIP:
+ return "TKIP"
+ case CCMP128:
+ return "CCMP-128"
+ case WEP104:
+ return "WEP-104"
+ case GCMP128:
+ return "GCMP-128"
+ case GCMP256:
+ return "GCMP-256"
+ case CCMP256:
+ return "CCMP-256"
+ case BIPCMAC128:
+ return "BIP-CMAC-128"
+ case BIPGMAC128:
+ return "BIP-GMAC-128"
+ case BIPGMAC256:
+ return "BIP-GMAC-256"
+ case SMS4:
+ return "SMS4"
+ case CKIP128:
+ return "CKIP-128"
+ case CKIP128_PMK:
+ return "CKIP-128 with PMK caching"
+ case CipherReserved3, CipherReserved15:
+ return "Reserved"
+ default:
+ return fmt.Sprintf("Unknown cipher suite (Value: %d)", c)
}
}
-func(a AKMSuite) String() string {
+func (a AKMSuite) String() string {
switch a {
- case IEEE8021X:
- return "802.1X"
- case PSK:
- return "PSK"
- case FT_8021X:
- return "FT over 802.1X"
- case FT_PSK:
- return "FT over PSK"
- case WPA_8021X:
- return "WPA with 802.1X"
- case WPA_PSK:
- return "WPA with PSK"
- case OWE:
- return "OWE"
- case OWE_Transition:
- return "OWE Transition Mode"
- case SAE:
- return "SAE"
- case FT_SAE:
- return "FT over SAE"
- case FILS_SHA256:
- return "FILS-SHA256"
- case FILS_SHA384:
- return "FILS-SHA384"
- case FT_FILS_SHA256:
- return "FT over FILS-SHA256"
- case FT_FILS_SHA384:
- return "FT over FILS-SHA384"
- case OWE_transition_mode:
- return "OWE transition mode"
- default:
- return fmt.Sprintf("Unknown or Reserved AKM suite (Value: %d)", a)
+ case IEEE8021X:
+ return "802.1X"
+ case PSK:
+ return "PSK"
+ case FT_8021X:
+ return "FT over 802.1X"
+ case FT_PSK:
+ return "FT over PSK"
+ case WPA_8021X:
+ return "WPA with 802.1X"
+ case WPA_PSK:
+ return "WPA with PSK"
+ case OWE:
+ return "OWE"
+ case OWE_Transition:
+ return "OWE Transition Mode"
+ case SAE:
+ return "SAE"
+ case FT_SAE:
+ return "FT over SAE"
+ case FILS_SHA256:
+ return "FILS-SHA256"
+ case FILS_SHA384:
+ return "FILS-SHA384"
+ case FT_FILS_SHA256:
+ return "FT over FILS-SHA256"
+ case FT_FILS_SHA384:
+ return "FT over FILS-SHA384"
+ case OWE_transition_mode:
+ return "OWE transition mode"
+ default:
+ return fmt.Sprintf("Unknown or Reserved AKM suite (Value: %d)", a)
}
}
diff --git a/go/plugin/caddy2/pfpki/models/models.go b/go/plugin/caddy2/pfpki/models/models.go
index cfe0b350d842..c1048cb75995 100644
--- a/go/plugin/caddy2/pfpki/models/models.go
+++ b/go/plugin/caddy2/pfpki/models/models.go
@@ -1243,7 +1243,10 @@ func (c Cert) New() (types.Info, error) {
Subject := c.MakeSubject()
- NotAfter := time.Now().AddDate(0, 0, prof.Validity)
+ NotAfter := c.ValidUntil
+ if c.ValidUntil.IsZero() {
+ NotAfter = time.Now().AddDate(0, 0, prof.Validity)
+ }
// Prepare certificate
cert := &x509.Certificate{
@@ -1268,6 +1271,7 @@ func (c Cert) New() (types.Info, error) {
if len(c.Mail) > 0 {
Email = c.Mail
}
+
if len(Email) > 0 {
for _, mail := range strings.Split(Email, ",") {
cert.EmailAddresses = append(cert.EmailAddresses, mail)
diff --git a/html/captive-portal/lib/captiveportal/PacketFence/DynamicRouting/Module/TLSEnrollment.pm b/html/captive-portal/lib/captiveportal/PacketFence/DynamicRouting/Module/TLSEnrollment.pm
index a0a605271e57..e006d6435015 100644
--- a/html/captive-portal/lib/captiveportal/PacketFence/DynamicRouting/Module/TLSEnrollment.pm
+++ b/html/captive-portal/lib/captiveportal/PacketFence/DynamicRouting/Module/TLSEnrollment.pm
@@ -195,7 +195,7 @@ sub get_bundle {
my $mac = $self->current_mac;
my $user_cache = $self->app->user_cache;
my $pki_session = $user_cache->compute("pki_session", sub {});
- my $cert_content = $pki_provider->get_bundle({ certificate_email => $pki_session->{certificate_email}, certificate_cn => $pki_session->{certificate_cn}, certificate_pwd => $pki_session->{certificate_pwd} });
+ my $cert_content = $pki_provider->get_bundle({ certificate_email => $pki_session->{certificate_email}, certificate_cn => $pki_session->{certificate_cn}, certificate_pwd => $pki_session->{certificate_pwd}, unregdate => $self->new_node_info->{'unregdate'}});
get_logger->debug(sub { "cert_content from pki service $cert_content" });
unless(defined($cert_content)){
diff --git a/html/pfappserver/root/src/views/Configuration/pkiProviders/_components/FormTypePacketfencePki.vue b/html/pfappserver/root/src/views/Configuration/pkiProviders/_components/FormTypePacketfencePki.vue
index 7ad0062df9ec..c255e49eb65f 100644
--- a/html/pfappserver/root/src/views/Configuration/pkiProviders/_components/FormTypePacketfencePki.vue
+++ b/html/pfappserver/root/src/views/Configuration/pkiProviders/_components/FormTypePacketfencePki.vue
@@ -62,6 +62,13 @@
disabled-value="N"
/>
+
+
(is => 'rw', default => '%s');
has revoke_on_unregistration => (is => 'rw', default => 'N');
+has certificate_validity_time_from_unreg_date => (is => 'rw', default => 'N');
+
=head2 country
What country to use for the certificate
diff --git a/lib/pf/pki_provider/packetfence_pki.pm b/lib/pf/pki_provider/packetfence_pki.pm
index 211cfb444a9a..1839dd304f9f 100644
--- a/lib/pf/pki_provider/packetfence_pki.pm
+++ b/lib/pf/pki_provider/packetfence_pki.pm
@@ -20,6 +20,9 @@ use URI::Escape::XS qw(uri_escape uri_unescape);
use pf::api::unifiedapiclient;
use pf::dal::key_value_storage;
use pf::error qw(is_success is_error);
+use DateTime::TimeZone;
+use DateTime::Format::Strptime;
+use pf::util qw(isenabled);
extends 'pf::pki_provider';
@@ -55,11 +58,8 @@ sub get_bundle {
my $street = $self->streetaddress;
my $postalcode = $self->postalcode;
my $streetaddress = $self->streetaddress;
-
- my $certpwd = $args->{'certificate_pwd'};
-
- my $value = eval {
- my $return = pf::api::unifiedapiclient->default_client->call("POST", "/api/v1/pki/certs", {
+ my $expiration = $args->{'unregdate'};
+ my $payload = {
"cn" => $cn,
"mail" => $email,
"organisation" => $organisation,
@@ -69,7 +69,22 @@ sub get_bundle {
"postal_code" => $postalcode,
"street_address" => $streetaddress,
"profile_id" => $profile,
- });
+ };
+
+ if (defined($expiration) && $expiration ne "" && isenabled($self->certificate_validity_time_from_unreg_date) ) {
+ my $tz = $ENV{TZ} || DateTime::TimeZone->new( name => 'local' )->name();
+ my $formatter = DateTime::Format::Strptime->new(pattern => "%F %T",time_zone=>$tz);
+ my $dt_obj = $formatter->parse_datetime($expiration);
+ # to convert to a different zone:
+ $dt_obj->set_time_zone('UTC');
+ my $dt = $dt_obj->strftime("%Y-%m-%dT%T%z");
+ $dt =~ s/(.*)\+(\d{2})(\d{2})/$1Z/g;
+ $payload->{"valid_until"} = "$dt";
+ }
+ my $certpwd = $args->{'certificate_pwd'};
+
+ my $value = eval {
+ my $return = pf::api::unifiedapiclient->default_client->call("POST", "/api/v1/pki/certs", $payload);
};
if ($@) {
$logger->warn("Certificate creation failed");