mirror of
https://github.com/outbackdingo/labca.git
synced 2026-01-27 10:19:34 +00:00
Determine issuer NameID value so we can set the correct AIA URL (#35)
This commit is contained in:
@@ -64,6 +64,10 @@ if [ "$PKI_DOMAIN_MODE" == "lockdown" ] || [ "$PKI_DOMAIN_MODE" == "whitelist" ]
|
||||
cat rate-limit-policies.yml | tr '\n' '\r' | sed -e "s|\(certificatesPerFQDNSet:.*must-staple.le.wtf: 10000\).*\(certificatesPerFQDNSetFast:.*\)|\1\n${REPLACEMENT}rateLimitsURL: http://$PKI_FQDN/rate-limits\n\2|" | tr '\r' '\n' > rate-limit-policies.yml.bak && mv rate-limit-policies.yml.bak rate-limit-policies.yml
|
||||
fi
|
||||
|
||||
|
||||
sed -i -e "s|\"issuerURL\": \".*\"|\"issuerURL\": \"http://$PKI_FQDN/aia/issuer/$PKI_ISSUER_NAME_ID\"|" config/ca-a.json
|
||||
sed -i -e "s|\"issuerURL\": \".*\"|\"issuerURL\": \"http://$PKI_FQDN/aia/issuer/$PKI_ISSUER_NAME_ID\"|" config/ca-b.json
|
||||
|
||||
if [ "$PKI_EXTENDED_TIMEOUT" == "1" ]; then
|
||||
sed -i -e "s/\"timeout\": \"15s\"/\"timeout\": \"30s\"/" config/ca-a.json
|
||||
sed -i -e "s/\"timeout\": \"15s\"/\"timeout\": \"30s\"/" config/ca-b.json
|
||||
|
||||
@@ -102,7 +102,7 @@ func reportError(err error) error {
|
||||
|
||||
stop := len(lines)
|
||||
for i := 0; i < len(lines); i++ {
|
||||
if strings.Index(lines[i], ".ServeHTTP(") >= 0 {
|
||||
if strings.Contains(lines[i], ".ServeHTTP(") {
|
||||
stop = i
|
||||
break
|
||||
}
|
||||
@@ -218,14 +218,14 @@ func (ci *CertificateInfo) ImportPkcs12(tmpFile string, tmpKey string, tmpCert s
|
||||
}
|
||||
|
||||
if out, err := exeCmd("openssl pkcs12 -in " + strings.Replace(tmpFile, " ", "\\\\", -1) + " -password " + pwd + " -nocerts -nodes -out " + tmpKey); err != nil {
|
||||
if strings.Index(string(out), "invalid password") >= 0 {
|
||||
if strings.Contains(string(out), "invalid password") {
|
||||
return errors.New("incorrect password")
|
||||
}
|
||||
|
||||
return reportError(err)
|
||||
}
|
||||
if out, err := exeCmd("openssl pkcs12 -in " + strings.Replace(tmpFile, " ", "\\\\", -1) + " -password " + pwd + " -nokeys -out " + tmpCert); err != nil {
|
||||
if strings.Index(string(out), "invalid password") >= 0 {
|
||||
if strings.Contains(string(out), "invalid password") {
|
||||
return errors.New("incorrect password")
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ func (ci *CertificateInfo) Upload(path string, certBase string, tmpKey string, t
|
||||
}
|
||||
|
||||
if out, err := exeCmd("openssl pkey -passin " + pwd + " -in " + tmpKey + " -out " + tmpKey + "-out"); err != nil {
|
||||
if strings.Index(string(out), ":bad decrypt:") >= 0 {
|
||||
if strings.Contains(string(out), ":bad decrypt:") {
|
||||
return errors.New("incorrect password")
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ func (ci *CertificateInfo) ImportCerts(path string, rootCert string, rootKey str
|
||||
rootSubject = string(r[0 : len(r)-1])
|
||||
fmt.Printf("Import root with subject '%s'\n", rootSubject)
|
||||
|
||||
r, err = exeCmd("openssl pkey -noout -in " + rootKey)
|
||||
_, err = exeCmd("openssl pkey -noout -in " + rootKey)
|
||||
if err != nil {
|
||||
return reportError(err)
|
||||
}
|
||||
@@ -394,7 +394,7 @@ func (ci *CertificateInfo) ImportCerts(path string, rootCert string, rootKey str
|
||||
return errors.New("issuer not issued by our Root CA")
|
||||
}
|
||||
|
||||
r, err = exeCmd("openssl pkey -noout -in " + issuerKey)
|
||||
_, err = exeCmd("openssl pkey -noout -in " + issuerKey)
|
||||
if err != nil {
|
||||
return reportError(err)
|
||||
}
|
||||
@@ -577,8 +577,6 @@ func exeCmd(cmd string) ([]byte, error) {
|
||||
out, err := exec.Command(head, parts...).CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Print(fmt.Sprint(err) + ": " + string(out))
|
||||
} else {
|
||||
//fmt.Println(string(out))
|
||||
}
|
||||
return out, err
|
||||
}
|
||||
|
||||
@@ -86,10 +86,10 @@ func _parseLine(line string, loc *time.Location) Activity {
|
||||
if idx > -1 {
|
||||
message = message[0:idx]
|
||||
}
|
||||
if strings.Index(message, "Checked CAA records for") > -1 {
|
||||
if strings.Contains(message, "Checked CAA records for") {
|
||||
message = message[0:strings.Index(message, ",")]
|
||||
}
|
||||
if strings.Index(message, "Validation result") > -1 {
|
||||
if strings.Contains(message, "Validation result") {
|
||||
message = message[0:30]
|
||||
}
|
||||
idx = strings.Index(message, " csr=[")
|
||||
@@ -108,16 +108,16 @@ func _parseLine(line string, loc *time.Location) Activity {
|
||||
if idx > -1 {
|
||||
message = message[0:idx]
|
||||
}
|
||||
if strings.Index(message, "Certificate request - ") > -1 {
|
||||
if strings.Contains(message, "Certificate request - ") {
|
||||
idx = strings.Index(message, " JSON={")
|
||||
if idx > -1 {
|
||||
message = message[0:idx]
|
||||
}
|
||||
}
|
||||
if strings.Index(message, "failed to complete security handshake") > -1 {
|
||||
if strings.Contains(message, "failed to complete security handshake") {
|
||||
activity.Class = "warning"
|
||||
}
|
||||
if strings.Index(message, "failed to receive the preface from client") > -1 {
|
||||
if strings.Contains(message, "failed to receive the preface from client") {
|
||||
activity.Class = "warning"
|
||||
}
|
||||
activity.Message = message
|
||||
|
||||
66
gui/main.go
66
gui/main.go
@@ -4,11 +4,14 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
@@ -16,6 +19,7 @@ import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -137,9 +141,9 @@ func (reg *User) Validate(isNew bool, isChange bool) bool {
|
||||
}
|
||||
|
||||
if isNew || isChange {
|
||||
re := regexp.MustCompile(".+@.+\\..+")
|
||||
re := regexp.MustCompile(`.+@.+\..+`)
|
||||
matched := re.Match([]byte(reg.Email))
|
||||
if matched == false {
|
||||
if !matched {
|
||||
reg.Errors["Email"] = "Please enter a valid email address"
|
||||
}
|
||||
}
|
||||
@@ -1386,6 +1390,27 @@ func _buildCI(r *http.Request, session *sessions.Session, isRoot bool) *Certific
|
||||
return ci
|
||||
}
|
||||
|
||||
func issuerNameID(certfile string) (int64, error) {
|
||||
cf, err := ioutil.ReadFile(certfile)
|
||||
if err != nil {
|
||||
log.Printf("issuerNameID: could not read cert file: %v", err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
cpb, _ := pem.Decode(cf)
|
||||
crt, err := x509.ParseCertificate(cpb.Bytes)
|
||||
if err != nil {
|
||||
log.Printf("issuerNameID: could not parse x509 file: %v", err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// From issuance/issuance.go : func truncatedHash
|
||||
h := crypto.SHA1.New()
|
||||
h.Write(crt.RawSubject)
|
||||
s := h.Sum(nil)
|
||||
return int64(big.NewInt(0).SetBytes(s[:7]).Int64()), nil
|
||||
}
|
||||
|
||||
func _certCreate(w http.ResponseWriter, r *http.Request, certBase string, isRoot bool) bool {
|
||||
path := "data/"
|
||||
if !isRoot {
|
||||
@@ -1452,6 +1477,16 @@ func _certCreate(w http.ResponseWriter, r *http.Request, certBase string, isRoot
|
||||
return false
|
||||
}
|
||||
|
||||
if !ci.IsRoot {
|
||||
nameID, err := issuerNameID(path + certBase + ".pem")
|
||||
if err == nil {
|
||||
viper.Set("issuer_name_id", nameID)
|
||||
viper.WriteConfig()
|
||||
} else {
|
||||
log.Printf("_certCreate: could not calculate IssuerNameID: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if viper.Get("labca.organization") == nil {
|
||||
viper.Set("labca.organization", ci.Organization)
|
||||
viper.WriteConfig()
|
||||
@@ -1478,24 +1513,6 @@ func _certCreate(w http.ResponseWriter, r *http.Request, certBase string, isRoot
|
||||
return true
|
||||
}
|
||||
|
||||
func _parseLinuxIPRouteShow(output []byte) (net.IP, error) {
|
||||
// Linux '/usr/bin/ip route show' format looks like this:
|
||||
// default via 192.168.178.1 dev wlp3s0 metric 303
|
||||
// 192.168.178.0/24 dev wlp3s0 proto kernel scope link src 192.168.178.76 metric 303
|
||||
lines := strings.Split(string(output), "\n")
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) >= 3 && fields[0] == "default" {
|
||||
ip := net.ParseIP(fields[2])
|
||||
if ip != nil {
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("no gateway found")
|
||||
}
|
||||
|
||||
func _hostCommand(w http.ResponseWriter, r *http.Request, command string, params ...string) bool {
|
||||
conn, err := net.Dial("tcp", "control:3030")
|
||||
if err != nil {
|
||||
@@ -1563,6 +1580,7 @@ func _applyConfig() error {
|
||||
os.Setenv("PKI_DOMAIN_MODE", viper.GetString("labca.domain_mode"))
|
||||
os.Setenv("PKI_LOCKDOWN_DOMAINS", viper.GetString("labca.lockdown"))
|
||||
os.Setenv("PKI_WHITELIST_DOMAINS", viper.GetString("labca.whitelist"))
|
||||
os.Setenv("PKI_ISSUER_NAME_ID", viper.GetString("issuer_name_id"))
|
||||
if viper.GetBool("labca.extended_timeout") {
|
||||
os.Setenv("PKI_EXTENDED_TIMEOUT", "1")
|
||||
} else {
|
||||
@@ -1698,7 +1716,7 @@ func _setupAdminUser(w http.ResponseWriter, r *http.Request) bool {
|
||||
// Restore a backup file
|
||||
if isMultipart {
|
||||
reg := &User{
|
||||
Errors: make(map[string]string),
|
||||
Errors: make(map[string]string),
|
||||
RequestBase: r.Header.Get("X-Request-Base"),
|
||||
}
|
||||
file, header, err := r.FormFile("file")
|
||||
@@ -1918,14 +1936,14 @@ func setupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// 3. Setup root CA certificate
|
||||
if !_certCreate(w, r, "root-ca", true) {
|
||||
// Cleanup the cert (if it even exists) so we will retry on the next run
|
||||
_ := os.Remove("data/root-ca.pem")
|
||||
os.Remove("data/root-ca.pem")
|
||||
return
|
||||
}
|
||||
|
||||
// 4. Setup issuer certificate
|
||||
if !_certCreate(w, r, "ca-int", false) {
|
||||
// Cleanup the cert (if it even exists) so we will retry on the next run
|
||||
_ := os.Remove("data/issuer/ca-int.pem")
|
||||
os.Remove("data/issuer/ca-int.pem")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2083,7 +2101,7 @@ func accountsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Accounts, err := GetAccounts(w, r)
|
||||
if err == nil {
|
||||
render(w, r, "list:accounts", map[string]interface{}{"List": Accounts, "Title": "ACME"})
|
||||
render(w, r, "list:accounts", map[string]interface{}{"List": Accounts, "Title": "ACME"})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
17
install
17
install
@@ -455,6 +455,7 @@ static_web() {
|
||||
[ -d /home/labca/nginx_data/conf.d ] || mkdir -p /home/labca/nginx_data/conf.d
|
||||
[ -d /home/labca/nginx_data/ssl ] || mkdir -p /home/labca/nginx_data/ssl
|
||||
cp $cloneDir/nginx.conf /home/labca/nginx_data/conf.d/labca.conf
|
||||
cp $cloneDir/proxy.conf /home/labca/nginx_data/conf.d/proxy.conf
|
||||
if [ -f "$boulderLabCADir/setup_complete" ]; then
|
||||
perl -i -p0e 's/\n # BEGIN temporary redirect\n location = \/ \{\n return 302 \/admin\/;\n }\n # END temporary redirect\n//igs' /home/labca/nginx_data/conf.d/labca.conf
|
||||
fi
|
||||
@@ -646,10 +647,6 @@ config_boulder() {
|
||||
sed -i -e "s/5001/443/g" config/va-remote-b.json
|
||||
sed -i -e "s/5002/80/g" config/va-remote-b.json
|
||||
sed -i -e "s|https://boulder:4431/terms/v7|https://$LABCA_FQDN/terms/v1|" config/wfe2.json
|
||||
sed -i -e "s|http://boulder:4430/acme/issuer-cert|http://$LABCA_FQDN/certs/ca-int.der|" config/ca-a.json
|
||||
sed -i -e "s|http://boulder:4430/acme/issuer-cert|http://$LABCA_FQDN/certs/ca-int.der|" config/ca-b.json
|
||||
sed -i -e "s|http://127.0.0.1:4000/acme/issuer-cert|http://$LABCA_FQDN/certs/ca-int.der|" config/ca-a.json
|
||||
sed -i -e "s|http://127.0.0.1:4000/acme/issuer-cert|http://$LABCA_FQDN/certs/ca-int.der|" config/ca-b.json
|
||||
sed -i -e "s|http://boulder:4430/acme/issuer-cert|http://$LABCA_FQDN/acme/issuer-cert|" config/wfe2.json
|
||||
sed -i -e "s|http://127.0.0.1:4000/acme/issuer-cert|https://$LABCA_FQDN/acme/issuer-cert|" config/wfe2.json
|
||||
sed -i -e "s|letsencrypt/boulder|hakwerk/labca|" config/wfe2.json
|
||||
@@ -661,8 +658,6 @@ config_boulder() {
|
||||
sed -i -e "s|1.2.3.4|1.3.6.1.4.1.44947.1.1.1|g" config/ca-b.json
|
||||
perl -i -p0e "s/(\s+\"crlURL\":[^\n]*)//igs" config/ca-a.json
|
||||
perl -i -p0e "s/(\s+\"crlURL\":[^\n]*)//igs" config/ca-b.json
|
||||
sed -i -e "s/Do What Thou Wilt/This PKI is only meant for internal (lab) usage; do NOT use this on the open internet\!/g" config/ca-a.json
|
||||
sed -i -e "s/Do What Thou Wilt/This PKI is only meant for internal (lab) usage; do NOT use this on the open internet\!/g" config/ca-b.json
|
||||
sed -i -e "s/ocspURL.Path = encodedReq/ocspURL.Path += encodedReq/" ocsp/helper/helper.go
|
||||
sed -i -e "s/\"dnsTimeout\": \".*\"/\"dnsTimeout\": \"3s\"/" config/ra.json
|
||||
sed -i -e "s/\"dnsTimeout\": \".*\"/\"dnsTimeout\": \"3s\"/" config/va.json
|
||||
@@ -693,6 +688,16 @@ config_boulder() {
|
||||
export PKI_DOMAIN_MODE=$(grep domain_mode $adminDir/data/config.json | sed -e 's/.*:[ ]*//' | sed -e 's/\",//g' | sed -e 's/\"//g')
|
||||
export PKI_LOCKDOWN_DOMAINS=$(grep lockdown $adminDir/data/config.json | grep -v domain_mode | sed -e 's/.*:[ ]*//' | sed -e 's/\",//g' | sed -e 's/\"//g')
|
||||
export PKI_WHITELIST_DOMAINS=$(grep whitelist $adminDir/data/config.json | grep -v domain_mode | sed -e 's/.*:[ ]*//' | sed -e 's/\",//g' | sed -e 's/\"//g')
|
||||
export PKI_ISSUER_NAME_ID=$(grep issuer_name_id $adminDir/data/config.json | sed -e 's/.*:[ ]*//' | sed -e 's/\",//g' | sed -e 's/\"//g')
|
||||
if [ -z "$PKI_ISSUER_NAME_ID" ] && [ -e "$adminDir/data/issuer/ca-int.pem" ]; then
|
||||
local img=$(grep "&boulder_image" $boulderDir/docker-compose.yml | sed -e "s/.*boulder_image \(.*\)/\1/")
|
||||
eval img=$img
|
||||
docker run --rm -v $cloneDir/utils:/utils -w /utils $img go build nameidtool.go &>>$installLog
|
||||
nmid=$($cloneDir/utils/nameidtool $adminDir/data/issuer/ca-int.pem)
|
||||
if [ $? == 0 ]; then
|
||||
export PKI_ISSUER_NAME_ID=$nmid
|
||||
fi
|
||||
fi
|
||||
|
||||
enabled=$(grep "email\": {" $adminDir/data/config.json -A1 | grep enable | head -1 | perl -p0e 's/.*?:\s+(.*)/\1/' | sed -e 's/\",//g' | sed -e 's/\"//g')
|
||||
if [ "$enabled" == "true," ]; then
|
||||
|
||||
47
nginx.conf
47
nginx.conf
@@ -14,15 +14,17 @@ server {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
location /aia/issuer {
|
||||
include conf.d/proxy.conf;
|
||||
proxy_pass http://boulder:4001;
|
||||
}
|
||||
|
||||
location /directory {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
location /ocsp/ {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
location /ocsp {
|
||||
include conf.d/proxy.conf;
|
||||
proxy_pass http://boulder:4002/;
|
||||
}
|
||||
|
||||
@@ -55,20 +57,14 @@ server {
|
||||
}
|
||||
|
||||
location /admin/ {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
include conf.d/proxy.conf;
|
||||
proxy_set_header X-Request-Base "/admin";
|
||||
proxy_pass http://labca:3000/;
|
||||
error_page 502 504 /502.html;
|
||||
}
|
||||
|
||||
location /admin/ws {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
include conf.d/proxy.conf;
|
||||
proxy_set_header X-Request-Base "/admin";
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
@@ -76,26 +72,27 @@ server {
|
||||
}
|
||||
|
||||
location /acme/ {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
include conf.d/proxy.conf;
|
||||
proxy_pass http://boulder:4001;
|
||||
}
|
||||
|
||||
location /directory {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
include conf.d/proxy.conf;
|
||||
proxy_pass http://boulder:4001;
|
||||
}
|
||||
|
||||
location /build {
|
||||
include conf.d/proxy.conf;
|
||||
proxy_pass http://boulder:4001;
|
||||
}
|
||||
|
||||
location /aia/issuer {
|
||||
include conf.d/proxy.conf;
|
||||
proxy_pass http://boulder:4001;
|
||||
}
|
||||
|
||||
location /ocsp/ {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
include conf.d/proxy.conf;
|
||||
proxy_pass http://boulder:4002/;
|
||||
}
|
||||
|
||||
|
||||
4
proxy.conf
Normal file
4
proxy.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
46
utils/nameidtool.go
Normal file
46
utils/nameidtool.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
)
|
||||
|
||||
func issuerNameID(certfile string) (int64, error) {
|
||||
cf, err := ioutil.ReadFile(certfile)
|
||||
if err != nil {
|
||||
fmt.Printf("issuerNameID: could not read cert file: %v", err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
cpb, _ := pem.Decode(cf)
|
||||
crt, err := x509.ParseCertificate(cpb.Bytes)
|
||||
if err != nil {
|
||||
fmt.Printf("issuerNameID: could not parse x509 file: %v", err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// From issuance/issuance.go : func truncatedHash
|
||||
h := crypto.SHA1.New()
|
||||
h.Write(crt.RawSubject)
|
||||
s := h.Sum(nil)
|
||||
return int64(big.NewInt(0).SetBytes(s[:7]).Int64()), nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args[1:]) < 1 {
|
||||
fmt.Printf("Usage:\n %s <certificate.pem>\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
nameID, err := issuerNameID(os.Args[1])
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println(nameID)
|
||||
}
|
||||
Reference in New Issue
Block a user