in lib/persona/persona.go [265:397]
func populatePersonaVisas(ctx context.Context, pname, visaIssuer string, assertions []*cpb.Assertion, id *ga4gh.Identity) (*ga4gh.Identity, error) {
issuer := id.Issuer
jku := jkuURL(issuer)
id.GA4GH = make(map[string][]ga4gh.OldClaim)
id.VisaJWTs = make([]string, len(assertions))
now := float64(time.Now().Unix())
signer := signer(&personaKey)
for i, assert := range assertions {
typ := ga4gh.Type(assert.Type)
if len(typ) == 0 {
return nil, fmt.Errorf("persona %q visa %d missing assertion type", pname, i+1)
}
_, ok := id.GA4GH[assert.Type]
if !ok {
id.GA4GH[assert.Type] = make([]ga4gh.OldClaim, 0)
}
if len(assert.Value) == 0 {
return nil, fmt.Errorf("persona %q visa %d missing assertion value", pname, i+1)
}
src := ga4gh.Source(issuer)
if len(assert.Source) > 0 {
src = ga4gh.Source(assert.Source)
}
// assert.AssertedDuration cannot be negative and is assumed to be a duration in the past.
a, err := timeutil.ParseDuration(assert.AssertedDuration)
if err != nil {
return nil, fmt.Errorf("persona %q visa %d asserted duration %q: %v", pname, i+1, assert.AssertedDuration, err)
}
asserted := int64(now - a.Seconds())
// assert.ExpiresDuration may be negative or positive where a negative value represents the past.
e, err := timeutil.ParseDuration(assert.ExpiresDuration)
if err != nil {
return nil, fmt.Errorf("persona %q visa %d expires duration %q: %v", pname, i+1, assert.ExpiresDuration, err)
}
if e > 0 && e < minPersonaFutureExpiry {
e = minPersonaFutureExpiry
}
expires := int64(now + e.Seconds())
visa := ga4gh.VisaData{
StdClaims: ga4gh.StdClaims{
Subject: id.Subject,
Issuer: visaIssuer,
ExpiresAt: expires,
IssuedAt: int64(now),
},
Assertion: ga4gh.Assertion{
Type: typ,
Value: ga4gh.Value(assert.Value),
Source: src,
Asserted: asserted,
By: ga4gh.By(assert.By),
},
}
if len(assert.AnyOfConditions) > 0 {
visa.Assertion.Conditions = make(ga4gh.Conditions, 0)
for _, cond := range assert.AnyOfConditions {
clauses := []ga4gh.Condition{}
for _, clause := range cond.AllOf {
c := ga4gh.Condition{
Type: ga4gh.Type(clause.Type),
Value: ga4gh.Pattern(clause.Value),
Source: ga4gh.Pattern(clause.Source),
By: ga4gh.Pattern(clause.By),
}
clauses = append(clauses, c)
}
visa.Assertion.Conditions = append(visa.Assertion.Conditions, clauses)
}
}
v, err := ga4gh.NewVisaFromData(ctx, &visa, jku, signer)
if err != nil {
return nil, fmt.Errorf("signing persona %q visa %d failed: %s", pname, i+1, err)
}
id.VisaJWTs[i] = string(v.JWT())
// Populate old claims.
c := ga4gh.OldClaim{
Value: assert.Value,
Source: string(src),
Asserted: float64(asserted),
Expires: float64(expires),
By: assert.By,
}
if len(assert.AnyOfConditions) > 0 {
c.Condition = make(map[string]ga4gh.OldClaimCondition)
cType := ""
cValue := []string{}
cSource := []string{}
cBy := []string{}
for _, cond := range assert.AnyOfConditions {
for _, clause := range cond.AllOf {
cType = clause.Type
clValue := clause.Value
if clValues := strings.SplitN(clause.Value, ":", 2); len(clValues) > 1 {
clValue = clValues[1]
}
clSource := clause.Source
if clSources := strings.SplitN(clause.Source, ":", 2); len(clSources) > 1 {
clSource = clSources[1]
}
clBy := clause.By
if clBys := strings.SplitN(clause.By, ":", 2); len(clBys) > 1 {
clBy = clBys[1]
}
if len(clValue) > 0 {
cValue = append(cValue, clValue)
}
if len(clSource) > 0 {
cSource = append(cSource, clSource)
}
if len(clBy) > 0 {
cBy = append(cBy, clBy)
}
}
}
oldC := ga4gh.OldClaimCondition{}
if len(cValue) > 0 {
oldC.Value = cValue
}
if len(cSource) > 0 {
oldC.Source = cSource
}
if len(cBy) > 0 {
oldC.By = cBy
}
c.Condition[cType] = oldC
}
id.GA4GH[assert.Type] = append(id.GA4GH[assert.Type], c)
}
return id, nil
}