为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕娘9325324 2022-04-26 10:49:05
我正在尝试使用以下 Go 脚本将自签名证书添加到 MacOS 设备上的系统钥匙串:package mainimport (    "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.goPassword: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页面中记录了它)?
查看完整描述

1 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

在https://www.jamf.com/jamf-nation/discussions/13812/problems-importing-cert-via-terminal之后,我通过编写包含证书的配置文件并使用profiles命令行工具安装它来解决这个问题而不是security直接使用那个。这是改编后的脚本:


package main


import (

    "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 profile

func NewProfile() *Profile {

    payloadUUID := uuid.NewV4()


    return &Profile{

        PayloadVersion: 1,

        PayloadType:    "Configuration",

        PayloadUUID:    payloadUUID.String(),

    }

}


// NewPayload creates a new payload

func 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.的证书在我的钥匙串中显示为受信任的证书:

//img1.sycdn.imooc.com//62675dda0001baf513810039.jpg

查看完整回答
反对 回复 2022-04-26
  • 1 回答
  • 0 关注
  • 570 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号