Skip to content

Commit 46d079d

Browse files
authored
Merge pull request #68 from synadia-io/fix-67
Add SetIssuer method for account operator key selection
2 parents dae8c8d + 7384ff6 commit 46d079d

File tree

4 files changed

+82
-22
lines changed

4 files changed

+82
-22
lines changed

accounts.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,31 @@ func (a *AccountData) Issuer() string {
6161
return a.Claim.Issuer
6262
}
6363

64+
func (a *AccountData) SetIssuer(issuer string) error {
65+
if issuer != "" {
66+
_, err := KeyFrom(issuer, nkeys.PrefixByteOperator)
67+
if err != nil {
68+
return err
69+
}
70+
}
71+
72+
found := issuer == "" || a.Operator.Key.Public == issuer
73+
if !found {
74+
for i := 0; i < len(a.Operator.OperatorSigningKeys); i++ {
75+
if a.Operator.OperatorSigningKeys[i].Public == issuer {
76+
found = true
77+
break
78+
}
79+
}
80+
}
81+
82+
if !found {
83+
return fmt.Errorf("issuer is not a registered operator key")
84+
}
85+
a.Claim.Issuer = issuer
86+
return a.update()
87+
}
88+
6489
func (a *AccountData) update() error {
6590
if a.BaseData.readOnly {
6691
return fmt.Errorf("account is read-only")
@@ -71,12 +96,19 @@ func (a *AccountData) update() error {
7196
if vr.IsBlocking(true) {
7297
return vr.Errors()[0]
7398
}
74-
// FIXME: the account possibly needs a way to select the key...
75-
key := a.Operator.Key
76-
if len(a.Operator.OperatorSigningKeys) > 0 {
77-
key = a.Operator.OperatorSigningKeys[0]
99+
if a.Claim.Issuer == "" {
100+
a.Claim.Issuer = a.Operator.Key.Public
101+
}
102+
103+
if a.Claim.Issuer == a.Operator.Key.Public {
104+
return a.issue(a.Operator.Key)
105+
}
106+
for i := 0; i < len(a.Operator.OperatorSigningKeys); i++ {
107+
if a.Claim.Issuer == a.Operator.OperatorSigningKeys[0].Public {
108+
return a.issue(a.Operator.OperatorSigningKeys[i])
109+
}
78110
}
79-
return a.issue(key)
111+
return fmt.Errorf("operator signing key %q is was not found", a.Claim.Issuer)
80112
}
81113

82114
func (a *AccountData) getRevocations() jwt.RevocationList {

tests/accounts_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,3 +1070,42 @@ func (t *ProviderSuite) Test_SubjectMapping() {
10701070
t.NoError(sm.Delete("foo"))
10711071
t.NoError(sm.Delete("foo"))
10721072
}
1073+
1074+
func (t *ProviderSuite) Test_AccountIssuer() {
1075+
auth, err := authb.NewAuth(t.Provider)
1076+
t.NoError(err)
1077+
1078+
operators := auth.Operators()
1079+
t.Empty(operators.List())
1080+
1081+
o, err := operators.Add("O")
1082+
t.NoError(err)
1083+
t.NotNil(o)
1084+
1085+
a, err := o.Accounts().Add("A")
1086+
t.NoError(err)
1087+
t.NotNil(a)
1088+
1089+
t.Equal(a.Issuer(), o.Subject())
1090+
1091+
bad, err := authb.KeyFor(nkeys.PrefixByteAccount)
1092+
t.NoError(err)
1093+
err = a.SetIssuer(bad.Public)
1094+
t.Error(err)
1095+
t.Equal(err.Error(), "nkeys: incompatible key")
1096+
1097+
unknown, err := authb.KeyFor(nkeys.PrefixByteOperator)
1098+
t.NoError(err)
1099+
err = a.SetIssuer(unknown.Public)
1100+
t.Error(err)
1101+
t.Equal(err.Error(), "issuer is not a registered operator key")
1102+
1103+
sk, err := o.SigningKeys().Add()
1104+
t.NoError(err)
1105+
t.NotEmpty(sk)
1106+
t.NoError(a.SetIssuer(sk))
1107+
t.Equal(a.Issuer(), sk)
1108+
1109+
t.NoError(a.SetIssuer(""))
1110+
t.Equal(a.Issuer(), o.Subject())
1111+
}

tests/operator_test.go

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -184,23 +184,6 @@ func (t *ProviderSuite) Test_OperatorUsesMainKeyToSignAccount() {
184184
t.NoError(auth.Commit())
185185
}
186186

187-
func (t *ProviderSuite) Test_OperatorUsesSigningKeyToSignAccount() {
188-
auth, err := authb.NewAuth(t.Provider)
189-
t.NoError(err)
190-
o, err := auth.Operators().Add("O")
191-
t.NoError(err)
192-
sk, err := o.SigningKeys().Add()
193-
t.NoError(err)
194-
t.NotEmpty(sk)
195-
a, err := o.Accounts().Add("A")
196-
t.NoError(err)
197-
t.NotNil(sk, a.Issuer())
198-
t.NoError(auth.Commit())
199-
200-
ac := t.Store.GetAccount("O", "A")
201-
t.Equal(sk, ac.ClaimsData.Issuer)
202-
}
203-
204187
func (t *ProviderSuite) Test_OperatorRotate() {
205188
auth, err := authb.NewAuth(t.Provider)
206189
t.NoError(err)
@@ -211,6 +194,9 @@ func (t *ProviderSuite) Test_OperatorRotate() {
211194
t.NotEmpty(sk)
212195
a, err := o.Accounts().Add("A")
213196
t.NoError(err)
197+
t.Equal(o.Subject(), a.Issuer())
198+
199+
t.NoError(a.SetIssuer(sk))
214200
t.Equal(sk, a.Issuer())
215201
t.NoError(auth.Commit())
216202

types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,9 @@ type Account interface {
312312
// SetExpiry sets the expiry for the account in Unix Time Seconds.
313313
// 0 never expires.
314314
SetExpiry(exp int64) error
315+
// SetIssuer sets the operator key to use (default is operator). If
316+
// set to empty string, it will use the operator identity key
317+
SetIssuer(issuer string) error
315318
// Expiry returns the expiry for the account in Unix Time Seconds.
316319
// 0 never expires
317320
Expiry() int64

0 commit comments

Comments
 (0)