将自签名证书作为受信任的根证书添加到 Apple 钥匙串

我正在尝试使用以下 Go 脚本将自签名证书添加到 MacOS 设备上的系统钥匙串:


package main


import (

    "crypto/rand"

    "crypto/rsa"

    "crypto/x509"

    "crypto/x509/pkix"

    "encoding/pem"

    "math/big"

    "os"

    "os/exec"

    "time"


    "github.com/sirupsen/logrus"

)


func main() {

    keyFileName := "key.pem"

    certFileName := "cert.pem"


    // Generate a self-signed certificate (adapted from https://golang.org/src/crypto/tls/generate_cert.go)

    key, err := rsa.GenerateKey(rand.Reader, 4096)

    if err != nil {

        logrus.WithError(err).Fatal("generate key")

    }


    keyFile, err := os.Create(keyFileName)

    if err != nil {

        logrus.WithError(err).Fatal("create key file")

    }

    if err = pem.Encode(keyFile, &pem.Block{

        Type:  "RSA PRIVATE KEY",

        Bytes: x509.MarshalPKCS1PrivateKey(key),

    }); err != nil {

        logrus.WithError(err).Fatal("marshal private key")

    }

    keyFile.Close()


    template := x509.Certificate{

        SerialNumber: big.NewInt(42),

        Subject: pkix.Name{

            Country:            []string{"US"},

            Organization:       []string{"Awesomeness, Inc."},

            OrganizationalUnit: []string{"Awesomeness Dept."},

            CommonName:         "Awesomeness, Inc.",

        },

        NotBefore:             time.Now(),

        NotAfter:              time.Now().AddDate(10, 0, 0),

        KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,

        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},

        IsCA:                  true,

        BasicConstraintsValid: true,

    }


但是,当我使用 运行此脚本时sudo,我得到一个相当不确定的“传递给函数的一个或多个参数无效”。错误:


> sudo go run add_to_keychain_trusted.go

Password:

FATA[0002] add-trusted-cert: exit status 1 - SecTrustSettingsSetTrustSettings: One or more parameters passed to a function were not valid. 

exit status 1

我注意到的一件事是,如果我使用-r trustRoot选项而不是-r trustAsRoot,则该命令有效。也许-r trustAsRoot不再支持该选项(尽管man security页面中记录了它)?


慕娘9325324
浏览 572回答 1
1回答

慕森卡

在https://www.jamf.com/jamf-nation/discussions/13812/problems-importing-cert-via-terminal之后,我通过编写包含证书的配置文件并使用profiles命令行工具安装它来解决这个问题而不是security直接使用那个。这是改编后的脚本:package mainimport (    "crypto/rand"    "crypto/rsa"    "crypto/x509"    "crypto/x509/pkix"    "encoding/pem"    "io/ioutil"    "math/big"    "os"    "os/exec"    "strings"    "time"    uuid "github.com/satori/go.uuid"    "github.com/sirupsen/logrus"    "howett.net/plist")// Payload represents a configuration profile's payload. (Adapted from https://github.com/micromdm/micromdm/blob/master/mdm/enroll/profile.go).type Payload struct {    PayloadType         string      `json:"type"`    PayloadVersion      int         `json:"version"`    PayloadIdentifier   string      `json:"identifier"`    PayloadUUID         string      `json:"uuid"`    PayloadDisplayName  string      `json:"displayname" plist:",omitempty"`    PayloadDescription  string      `json:"description,omitempty" plist:",omitempty"`    PayloadOrganization string      `json:"organization,omitempty" plist:",omitempty"`    PayloadScope        string      `json:"scope" plist:",omitempty"`    PayloadContent      interface{} `json:"content,omitempty" plist:"PayloadContent,omitempty"`}// Profile represents a configuration profile (cf. https://developer.apple.com/business/documentation/Configuration-Profile-Reference.pdf)type Profile struct {    PayloadContent           []interface{}     `json:"content,omitempty"`    PayloadDescription       string            `json:"description,omitempty" plist:",omitempty"`    PayloadDisplayName       string            `json:"displayname,omitempty" plist:",omitempty"`    PayloadExpirationDate    *time.Time        `json:"expiration_date,omitempty" plist:",omitempty"`    PayloadIdentifier        string            `json:"identifier"`    PayloadOrganization      string            `json:"organization,omitempty" plist:",omitempty"`    PayloadUUID              string            `json:"uuid"`    PayloadRemovalDisallowed bool              `json:"removal_disallowed" plist:",omitempty"`    PayloadType              string            `json:"type"`    PayloadVersion           int               `json:"version"`    PayloadScope             string            `json:"scope" plist:",omitempty"`    RemovalDate              *time.Time        `json:"removal_date" plist:"-" plist:",omitempty"`    DurationUntilRemoval     float32           `json:"duration_until_removal" plist:",omitempty"`    ConsentText              map[string]string `json:"consent_text" plist:",omitempty"`}type CertificatePayload struct {    Payload    PayloadContent             []byte    PayloadCertificateFileName string `plist:",omitempty"`    Password                   string `plist:",omitempty"`    AllowAllAppsAccess         bool   `plist:",omitempty"`}// NewProfile creates a new configuration profilefunc NewProfile() *Profile {    payloadUUID := uuid.NewV4()    return &Profile{        PayloadVersion: 1,        PayloadType:    "Configuration",        PayloadUUID:    payloadUUID.String(),    }}// NewPayload creates a new payloadfunc NewPayload(payloadType string) *Payload {    payloadUUID := uuid.NewV4()    return &Payload{        PayloadVersion: 1,        PayloadType:    payloadType,        PayloadUUID:    payloadUUID.String(),    }}func NewCertificateProfile(certPEM []byte) *Profile {    profile := NewProfile()    profile.PayloadDescription = "Awesome Payload"    profile.PayloadDisplayName = "Awesome Certificate"    profile.PayloadIdentifier = "com.awesomeness.certificate"    profile.PayloadScope = "System"    profile.PayloadOrganization = "Awesomeness, Inc."    payload := NewPayload("com.apple.security.pem")    payload.PayloadDescription = "Awesome Certificate"    payload.PayloadDisplayName = "Awesome Certificate"    payload.PayloadOrganization = "Awesomeness, Inc."    payload.PayloadIdentifier = profile.PayloadIdentifier + "." + payload.PayloadUUID    certificatePayload := CertificatePayload{        Payload:        *payload,        PayloadContent: certPEM,    }    profile.PayloadContent = []interface{}{certificatePayload}    return profile}func generateSelfSignedCertificate(keyFileName, certFileName string) {    // Generate a self-signed certificate (adapted from https://golang.org/src/crypto/tls/generate_cert.go)    key, err := rsa.GenerateKey(rand.Reader, 4096)    if err != nil {        logrus.WithError(err).Fatal("generate key")    }    keyFile, err := os.Create(keyFileName)    if err != nil {        logrus.WithError(err).Fatal("create key file")    }    if err = pem.Encode(keyFile, &pem.Block{        Type:  "RSA PRIVATE KEY",        Bytes: x509.MarshalPKCS1PrivateKey(key),    }); err != nil {        logrus.WithError(err).Fatal("marshal private key")    }    keyFile.Close()    template := x509.Certificate{        SerialNumber: big.NewInt(42),        Subject: pkix.Name{            Country:            []string{"US"},            Organization:       []string{"Awesomeness, Inc."},            OrganizationalUnit: []string{"Awesomeness Dept."},            CommonName:         "Awesomeness 4, Inc.",        },        NotBefore:             time.Now(),        NotAfter:              time.Now().AddDate(10, 0, 0),        KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},        IsCA:                  true,        BasicConstraintsValid: true,    }    derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)    if err != nil {        logrus.WithError(err).Fatal("failed to create certificate")    }    certFile, err := os.Create(certFileName)    if err != nil {        logrus.WithError(err).Fatal("create cert file")    }    if err = pem.Encode(certFile, &pem.Block{        Type:  "CERTIFICATE",        Bytes: derBytes,    }); err != nil {        logrus.WithError(err).Fatal("encode certificate")    }    certFile.Close()}func main() {    keyFileName := "key.pem"    certFileName := "cert.pem"    profileFileName := "certificate.mobileconfig"    generateSelfSignedCertificate(keyFileName, certFileName)    certPEM, err := ioutil.ReadFile(certFileName)    if err != nil {        logrus.WithError(err).Fatal("read certificate file")    }    certificateProfile := NewCertificateProfile(certPEM)    mobileconfig, err := plist.MarshalIndent(certificateProfile, plist.XMLFormat, "\t")    if err != nil {        logrus.WithError(err).Fatal("marshal plist")    }    if err := ioutil.WriteFile(profileFileName, mobileconfig, 0755); err != nil {        logrus.WithError(err).Fatal("write mobileconfig to file")    }    args := []string{"install", "-path", profileFileName}    output, err := exec.Command("/usr/bin/profiles", args...).CombinedOutput()    if err != nil {        logrus.Fatalf("%s: %v - %s", "/usr/bin/profiles"+strings.Join(args, " "), err, output)    }}使用 运行此命令后sudo -E go run add_certificate.go,具有通用名称Awesomeness 4, Inc.的证书在我的钥匙串中显示为受信任的证书:
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go