func (e *Engine) AppendCredential(ctx context.Context, notifier *observer.Notifier,
	cred *PlaintextCredentialEnvelope) (*PlaintextCredentialEnvelope, error) {

	n := notifier.Notifier(4)

	// Ensure we have an existing keyring for this credential's pathexp
	graphs, err := e.client.CredentialGraph.List(ctx, "", cred.Body.PathExp,
		e.session.AuthID())
	if err != nil {
		log.Printf("Error retrieving credential graphs: %s", err)
		return nil, err
	}

	n.Notify(observer.Progress, "Credentials retrieved", true)

	sigID, encID, kp, err := fetchKeyPairs(ctx, e.client, cred.Body.OrgID)
	if err != nil {
		log.Printf("Error fetching keypairs: %s", err)
		return nil, err
	}

	n.Notify(observer.Progress, "Keypairs retrieved", true)

	cgs := newCredentialGraphSet()
	err = cgs.Add(graphs...)
	if err != nil {
		return nil, err
	}

	// Find the credentialgraph/keyring that we should store our credential in
	graph, err := cgs.Head(cred.Body.PathExp)
	if err != nil {
		return nil, err
	}

	// Find the  most recent version of this credential to act as our previous.
	previousCred, err := cgs.HeadCredential(cred.Body.PathExp, cred.Body.Name)
	if err != nil {
		log.Printf("error finding credentials to match: %s", err)
		return nil, err
	}

	var newGraph *registry.CredentialGraphV2
	// No matching CredentialGraph/KeyRing for this credential.
	// We'll make a new one now.
	if graph == nil || graph.HasRevocations() {
		newGraph, err = createCredentialGraph(ctx, cred.Body, graph, sigID,
			encID, kp, e.client, e.crypto)
		if err != nil {
			log.Printf("error creating credential graph: %s", err)
			return nil, err
		}
		cgs.Add(newGraph)
		graph = newGraph
	}

	// Construct an encrypted and signed version of the credential
	credBody := primitive.Credential{
		State: cred.Body.State,
		BaseCredential: primitive.BaseCredential{
			Name:      cred.Body.Name,
			PathExp:   cred.Body.PathExp,
			KeyringID: graph.GetKeyring().ID,
			ProjectID: cred.Body.ProjectID,
			OrgID:     cred.Body.OrgID,
			Credential: &primitive.CredentialValue{
				Algorithm: crypto.SecretBox,
			},
		},
	}

	if previousCred == nil {
		log.Printf("no previous")
		credBody.Previous = nil
		credBody.CredentialVersion = 1
	} else {
		base, err := baseCredential(previousCred)
		if err != nil {
			return nil, err
		}

		credBody.Previous = previousCred.ID
		credBody.CredentialVersion = base.CredentialVersion + 1
	}

	krm, mekshare, err := graph.FindMember(e.session.AuthID())
	if err != nil {
		log.Printf("Error finding keyring membership: %s", err)
		return nil, err
	}

	encryptingKey, err := findEncryptingKey(ctx, e.client, credBody.OrgID,
		krm.EncryptingKeyID)
	if err != nil {
		log.Printf("Error finding encrypting key: %s", err)
		return nil, err
	}

	n.Notify(observer.Progress, "Encrypting key retrieved", true)

	// Derive a key for the credential using the keyring master key
	// and use the derived key to encrypt the credential
	cekNonce, ctNonce, ct, err := e.crypto.BoxCredential(
		ctx, []byte(cred.Body.Value), *mekshare.Key.Value, *mekshare.Key.Nonce,
		&kp.Encryption, *encryptingKey.Key.Value)
	if err != nil {
		log.Printf("Error encrypting credential: %s", err)
		return nil, err
	}

	credBody.Nonce = base64.NewValue(cekNonce)

	credBody.Credential.Nonce = base64.NewValue(ctNonce)
	credBody.Credential.Value = base64.NewValue(ct)

	signed, err := e.crypto.SignedEnvelope(ctx, &credBody, sigID, &kp.Signature)
	if err != nil {
		log.Printf("Error signing credential body: %s", err)
		return nil, err
	}

	n.Notify(observer.Progress, "Credential encrypted", true)

	if newGraph != nil {
		newGraph.Credentials = []envelope.Signed{*signed}
		_, err = e.client.CredentialGraph.Post(ctx, &graph)
	} else {
		_, err = e.client.Credentials.Create(ctx, signed)
	}

	if err != nil {
		log.Printf("error creating credential: %s", err)
		return nil, err
	}

	return cred, nil
}
// AppendCredential attempts to append a plain-text Credential object to the
// Credential Graph.
AppendCredential attempts to append a plain-text Credential object to the
Credential Graph.
// AppendCredential attempts to append a plain - text Credential object to the // Credential Graph .
func (e *Engine) AppendCredential(ctx context.Context, notifier *observer.Notifier,
	cred *PlaintextCredentialEnvelope) (*PlaintextCredentialEnvelope, error) {
	n := notifier.Notifier(4)
	graphs, err := e.client.CredentialGraph.List(ctx, "", cred.Body.PathExp,
		e.session.AuthID())
	if err != nil {
		log.Printf("Error retrieving credential graphs: %s", err)
		return nil, err
	}
	n.Notify(observer.Progress, "Credentials retrieved", true)
	sigID, encID, kp, err := fetchKeyPairs(ctx, e.client, cred.Body.OrgID)
	if err != nil {
		log.Printf("Error fetching keypairs: %s", err)
		return nil, err
	}
	n.Notify(observer.Progress, "Keypairs retrieved", true)
	cgs := newCredentialGraphSet()
	err = cgs.Add(graphs...)
	if err != nil {
		return nil, err
	}
	graph, err := cgs.Head(cred.Body.PathExp)
	if err != nil {
		return nil, err
	}
	previousCred, err := cgs.HeadCredential(cred.Body.PathExp, cred.Body.Name)
	if err != nil {
		log.Printf("error finding credentials to match: %s", err)
		return nil, err
	}
	var newGraph *registry.CredentialGraphV2
	if graph == nil || graph.HasRevocations() {
		newGraph, err = createCredentialGraph(ctx, cred.Body, graph, sigID,
			encID, kp, e.client, e.crypto)
		if err != nil {
			log.Printf("error creating credential graph: %s", err)
			return nil, err
		}
		cgs.Add(newGraph)
		graph = newGraph
	}
	credBody := primitive.Credential{
		State: cred.Body.State,
		BaseCredential: primitive.BaseCredential{
			Name:      cred.Body.Name,
			PathExp:   cred.Body.PathExp,
			KeyringID: graph.GetKeyring().ID,
			ProjectID: cred.Body.ProjectID,
			OrgID:     cred.Body.OrgID,
			Credential: &primitive.CredentialValue{
				Algorithm: crypto.SecretBox,
			},
		},
	}
	if previousCred == nil {
		log.Printf("no previous")
		credBody.Previous = nil
		credBody.CredentialVersion = 1
	} else {
		base, err := baseCredential(previousCred)
		if err != nil {
			return nil, err
		}
		credBody.Previous = previousCred.ID
		credBody.CredentialVersion = base.CredentialVersion + 1
	}
	krm, mekshare, err := graph.FindMember(e.session.AuthID())
	if err != nil {
		log.Printf("Error finding keyring membership: %s", err)
		return nil, err
	}
	encryptingKey, err := findEncryptingKey(ctx, e.client, credBody.OrgID,
		krm.EncryptingKeyID)
	if err != nil {
		log.Printf("Error finding encrypting key: %s", err)
		return nil, err
	}
	n.Notify(observer.Progress, "Encrypting key retrieved", true)
	cekNonce, ctNonce, ct, err := e.crypto.BoxCredential(
		ctx, []byte(cred.Body.Value), *mekshare.Key.Value, *mekshare.Key.Nonce,
		&kp.Encryption, *encryptingKey.Key.Value)
	if err != nil {
		log.Printf("Error encrypting credential: %s", err)
		return nil, err
	}
	credBody.Nonce = base64.NewValue(cekNonce)
	credBody.Credential.Nonce = base64.NewValue(ctNonce)
	credBody.Credential.Value = base64.NewValue(ct)
	signed, err := e.crypto.SignedEnvelope(ctx, &credBody, sigID, &kp.Signature)
	if err != nil {
		log.Printf("Error signing credential body: %s", err)
		return nil, err
	}
	n.Notify(observer.Progress, "Credential encrypted", true)
	if newGraph != nil {
		newGraph.Credentials = []envelope.Signed{*signed}
		_, err = e.client.CredentialGraph.Post(ctx, &graph)
	} else {
		_, err = e.client.Credentials.Create(ctx, signed)
	}
	if err != nil {
		log.Printf("error creating credential: %s", err)
		return nil, err
	}
	return cred, nil
}
func ( e * Engine ) AppendCredential ( ctx context . Context , notifier * observer . Notifier , cred * PlaintextCredentialEnvelope ) ( * PlaintextCredentialEnvelope , error ) { n := notifier . Notifier ( 4 ) graphs , err := e . client . CredentialGraph . List ( ctx , " " , cred . Body . PathExp , e . session . AuthID ( ) ) if err != nil { log . Printf ( " " , err ) return nil , err } n . Notify ( observer . Progress , " " , true ) sigID , encID , kp , err := fetchKeyPairs ( ctx , e . client , cred . Body . OrgID ) if err != nil { log . Printf ( " " , err ) return nil , err } n . Notify ( observer . Progress , " " , true ) cgs := newCredentialGraphSet ( ) err = cgs . Add ( graphs ... ) if err != nil { return nil , err } graph , err := cgs . Head ( cred . Body . PathExp ) if err != nil { return nil , err } previousCred , err := cgs . HeadCredential ( cred . Body . PathExp , cred . Body . Name ) if err != nil { log . Printf ( " " , err ) return nil , err } var newGraph * registry . CredentialGraphV2 if graph == nil || graph . HasRevocations ( ) { newGraph , err = createCredentialGraph ( ctx , cred . Body , graph , sigID , encID , kp , e . client , e . crypto ) if err != nil { log . Printf ( " " , err ) return nil , err } cgs . Add ( newGraph ) graph = newGraph } credBody := primitive . Credential { State : cred . Body . State , BaseCredential : primitive . BaseCredential { Name : cred . Body . Name , PathExp : cred . Body . PathExp , KeyringID : graph . GetKeyring ( ) . ID , ProjectID : cred . Body . ProjectID , OrgID : cred . Body . OrgID , Credential : & primitive . CredentialValue { Algorithm : crypto . SecretBox , } , } , } if previousCred == nil { log . Printf ( " " ) credBody . Previous = nil credBody . CredentialVersion = 1 } else { base , err := baseCredential ( previousCred ) if err != nil { return nil , err } credBody . Previous = previousCred . ID credBody . CredentialVersion = base . CredentialVersion + 1 } krm , mekshare , err := graph . FindMember ( e . session . AuthID ( ) ) if err != nil { log . Printf ( " " , err ) return nil , err } encryptingKey , err := findEncryptingKey ( ctx , e . client , credBody . OrgID , krm . EncryptingKeyID ) if err != nil { log . Printf ( " " , err ) return nil , err } n . Notify ( observer . Progress , " " , true ) cekNonce , ctNonce , ct , err := e . crypto . BoxCredential ( ctx , [ ] byte ( cred . Body . Value ) , * mekshare . Key . Value , * mekshare . Key . Nonce , & kp . Encryption , * encryptingKey . Key . Value ) if err != nil { log . Printf ( " " , err ) return nil , err } credBody . Nonce = base64 . NewValue ( cekNonce ) credBody . Credential . Nonce = base64 . NewValue ( ctNonce ) credBody . Credential . Value = base64 . NewValue ( ct ) signed , err := e . crypto . SignedEnvelope ( ctx , & credBody , sigID , & kp . Signature ) if err != nil { log . Printf ( " " , err ) return nil , err } n . Notify ( observer . Progress , " " , true ) if newGraph != nil { newGraph . Credentials = [ ] envelope . Signed { * signed } _ , err = e . client . CredentialGraph . Post ( ctx , & graph ) } else { _ , err = e . client . Credentials . Create ( ctx , signed ) } if err != nil { log . Printf ( " " , err ) return nil , err } return cred , nil }
AppendCredential attempts to append a plain-text Credential object to the
Credential Graph.
AppendCredential attempts to append a plain - text Credential object to the Credential Graph .
// Ensure we have an existing keyring for this credential's pathexp // Find the credentialgraph/keyring that we should store our credential in // Find the  most recent version of this credential to act as our previous. // No matching CredentialGraph/KeyRing for this credential. // We'll make a new one now. // Construct an encrypted and signed version of the credential // Derive a key for the credential using the keyring master key // and use the derived key to encrypt the credential