go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/network/resources/openpgp.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package resources 5 6 import ( 7 "encoding/hex" 8 "strings" 9 "time" 10 11 "github.com/ProtonMail/go-crypto/openpgp" 12 "github.com/ProtonMail/go-crypto/openpgp/packet" 13 "go.mondoo.com/cnquery/llx" 14 "go.mondoo.com/cnquery/providers-sdk/v1/plugin" 15 ) 16 17 func (p *mqlOpenpgpEntities) list(content string) ([]interface{}, error) { 18 entries, err := openpgp.ReadArmoredKeyRing(strings.NewReader(content)) 19 if err != nil { 20 return nil, err 21 } 22 23 res := []interface{}{} 24 // to create certificate resources 25 for i := range entries { 26 entity := entries[i] 27 28 if entity == nil { 29 continue 30 } 31 32 pubKey, err := newMqlOpenpgpPublicKey(p.MqlRuntime, entity.PrimaryKey) 33 if err != nil { 34 return nil, err 35 } 36 37 mqlCert, err := CreateResource(p.MqlRuntime, "openpgp.entity", map[string]*llx.RawData{ 38 "primaryPublicKey": llx.ResourceData(pubKey, "openpgp.publicKey"), 39 }) 40 if err != nil { 41 return nil, err 42 } 43 44 c := mqlCert.(*mqlOpenpgpEntity) 45 c._identities = entity.Identities 46 res = append(res, c) 47 } 48 return res, nil 49 } 50 51 func pgpAlgoString(algorithm packet.PublicKeyAlgorithm) string { 52 var pubKeyAlgo string 53 54 switch algorithm { 55 case packet.PubKeyAlgoRSA: 56 pubKeyAlgo = "rsa" 57 case packet.PubKeyAlgoRSAEncryptOnly: 58 pubKeyAlgo = "rsa_encrypt_only" 59 case packet.PubKeyAlgoRSASignOnly: 60 pubKeyAlgo = "rsa_sign_only" 61 case packet.PubKeyAlgoElGamal: 62 pubKeyAlgo = "elgamal" 63 case packet.PubKeyAlgoDSA: 64 pubKeyAlgo = "dsa" 65 case packet.PubKeyAlgoECDH: 66 pubKeyAlgo = "ecdh" 67 case packet.PubKeyAlgoECDSA: 68 pubKeyAlgo = "ecdsa" 69 case packet.PubKeyAlgoEdDSA: 70 pubKeyAlgo = "eddsa" 71 } 72 73 return pubKeyAlgo 74 } 75 76 func newMqlOpenpgpPublicKey(runtime *plugin.Runtime, publicKey *packet.PublicKey) (*mqlOpenpgpPublicKey, error) { 77 pubKeyAlgo := pgpAlgoString(publicKey.PubKeyAlgo) 78 // we ignore the error here since it happens only when no algorithm is found 79 bitlength, _ := publicKey.BitLength() 80 81 o, err := CreateResource(runtime, "openpgp.publicKey", map[string]*llx.RawData{ 82 "id": llx.StringData(publicKey.KeyIdString()), 83 "version": llx.IntData(int64(publicKey.Version)), 84 "fingerprint": llx.StringData(hex.EncodeToString(publicKey.Fingerprint)), 85 "keyAlgorithm": llx.StringData(pubKeyAlgo), 86 "bitLength": llx.IntData(int64(bitlength)), 87 "creationTime": llx.TimeData(publicKey.CreationTime), 88 }) 89 if err != nil { 90 return nil, err 91 } 92 93 return o.(*mqlOpenpgpPublicKey), nil 94 } 95 96 type mqlOpenpgpEntityInternal struct { 97 _identities map[string]*openpgp.Identity 98 } 99 100 func (r *mqlOpenpgpEntity) id() (string, error) { 101 fp := r.PrimaryPublicKey.Data.GetFingerprint() 102 if fp.Error != nil { 103 return "", fp.Error 104 } 105 return "openpgp.entity/" + fp.Data, nil 106 } 107 108 func (r *mqlOpenpgpEntity) identities() ([]interface{}, error) { 109 fp := r.PrimaryPublicKey.Data.GetFingerprint() 110 if fp.Error != nil { 111 return nil, fp.Error 112 } 113 114 res := []interface{}{} 115 for k := range r._identities { 116 identity := r._identities[k] 117 o, err := CreateResource(r.MqlRuntime, "openpgp.identity", map[string]*llx.RawData{ 118 "fingerprint": llx.StringData(fp.Data), 119 "id": llx.StringData(identity.UserId.Id), 120 "name": llx.StringData(identity.UserId.Name), 121 "email": llx.StringData(identity.UserId.Email), 122 "comment": llx.StringData(identity.UserId.Comment), 123 }) 124 if err != nil { 125 return nil, err 126 } 127 cur := o.(*mqlOpenpgpIdentity) 128 cur._signatures = identity.Signatures 129 130 res = append(res, cur) 131 } 132 133 return res, nil 134 } 135 136 func (r *mqlOpenpgpPublicKey) id() (string, error) { 137 return "openpgp.publickey/" + r.Fingerprint.Data, nil 138 } 139 140 type mqlOpenpgpIdentityInternal struct { 141 _signatures []*packet.Signature 142 } 143 144 func (r *mqlOpenpgpIdentity) id() (string, error) { 145 return "openpgp.identity/" + r.Fingerprint.Data + "/" + r.Name.Data, nil 146 } 147 148 func (r *mqlOpenpgpIdentity) signatures() ([]interface{}, error) { 149 res := []interface{}{} 150 for k := range r._signatures { 151 signature := r._signatures[k] 152 153 var signatureType string 154 switch signature.SigType { 155 case packet.SigTypeBinary: 156 signatureType = "binary" 157 case packet.SigTypeText: 158 signatureType = "text" 159 case packet.SigTypeGenericCert: 160 signatureType = "generic_cert" 161 case packet.SigTypePersonaCert: 162 signatureType = "persona_cert" 163 case packet.SigTypeCasualCert: 164 signatureType = "casual_cert" 165 case packet.SigTypePositiveCert: 166 signatureType = "positive_cert" 167 case packet.SigTypeSubkeyBinding: 168 signatureType = "subkey_binding" 169 case packet.SigTypePrimaryKeyBinding: 170 signatureType = "primary_key_binding" 171 case packet.SigTypeDirectSignature: 172 signatureType = "direct_signature" 173 case packet.SigTypeKeyRevocation: 174 signatureType = "key_revocation" 175 case packet.SigTypeSubkeyRevocation: 176 signatureType = "subkey_revocation" 177 case packet.SigTypeCertificationRevocation: 178 signatureType = "cert_revocation" 179 } 180 181 lifetime := int64(-1) 182 var expirationTime *llx.RawData 183 if signature.SigLifetimeSecs != nil { 184 // NOTE: this can potentially overflow 185 lifetime = int64(*signature.SigLifetimeSecs) 186 187 expiry := signature.CreationTime.Add(time.Duration(*signature.SigLifetimeSecs) * time.Second) 188 diff := expiry.Unix() - time.Now().Unix() 189 ts := llx.DurationToTime(diff) 190 expirationTime = llx.TimeData(ts) 191 } else { 192 expirationTime = llx.NilData 193 } 194 195 keyLifetime := int64(-1) 196 var keyExpirationTime *llx.RawData 197 if signature.KeyLifetimeSecs != nil { 198 // NOTE: this can potentially overflow 199 keyLifetime = int64(*signature.KeyLifetimeSecs) 200 201 expiry := signature.CreationTime.Add(time.Duration(*signature.KeyLifetimeSecs) * time.Second) 202 diff := expiry.Unix() - time.Now().Unix() 203 ts := llx.DurationToTime(diff) 204 keyExpirationTime = llx.TimeData(ts) 205 } else { 206 expirationTime = llx.NilData 207 } 208 209 o, err := CreateResource(r.MqlRuntime, "openpgp.signature", map[string]*llx.RawData{ 210 "fingerprint": llx.StringData(r.Fingerprint.Data), 211 "identityName": llx.StringData(r.Id.Data), 212 "hash": llx.StringData(signature.Hash.String()), 213 "version": llx.IntData(int64(signature.Version)), 214 "signatureType": llx.StringData(signatureType), 215 "keyAlgorithm": llx.StringData(pgpAlgoString(signature.PubKeyAlgo)), 216 "creationTime": llx.TimeData(signature.CreationTime), 217 "lifetimeSecs": llx.IntData(lifetime), 218 "expiresIn": expirationTime, 219 "keyLifetimeSecs": llx.IntData(keyLifetime), 220 "keyExpiresIn": keyExpirationTime, 221 }) 222 if err != nil { 223 return nil, err 224 } 225 sig := o.(*mqlOpenpgpSignature) 226 res = append(res, sig) 227 } 228 229 return res, nil 230 } 231 232 func (r *mqlOpenpgpSignature) id() (string, error) { 233 return "openpgp.identity/" + r.Fingerprint.Data + "/" + r.IdentityName.Data + "/" + r.Hash.Data, nil 234 }