mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
We issue validation warnings now to the log. Signed-off-by: Derek Collison <derek@nats.io>
109 lines
3.3 KiB
Go
109 lines
3.3 KiB
Go
// Copyright 2018 The NATS Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/nats-io/jwt"
|
|
"github.com/nats-io/nkeys"
|
|
)
|
|
|
|
var nscDecoratedRe = regexp.MustCompile(`\s*(?:(?:[-]{3,}[^\n]*[-]{3,}\n)(.+)(?:\n\s*[-]{3,}[^\n]*[-]{3,}[\n]*))`)
|
|
|
|
// All JWTs once encoded start with this
|
|
const jwtPrefix = "eyJ"
|
|
|
|
// readOperatorJWT
|
|
func readOperatorJWT(jwtfile string) (*jwt.OperatorClaims, error) {
|
|
contents, err := ioutil.ReadFile(jwtfile)
|
|
if err != nil {
|
|
// Check to see if the JWT has been inlined.
|
|
if !strings.HasPrefix(jwtfile, jwtPrefix) {
|
|
return nil, err
|
|
}
|
|
// We may have an inline jwt here.
|
|
contents = []byte(jwtfile)
|
|
}
|
|
defer wipeSlice(contents)
|
|
|
|
var claim string
|
|
items := nscDecoratedRe.FindAllSubmatch(contents, -1)
|
|
if len(items) == 0 {
|
|
claim = string(contents)
|
|
} else {
|
|
// First result should be the JWT.
|
|
// We copy here so that if the file contained a seed file too we wipe appropriately.
|
|
raw := items[0][1]
|
|
tmp := make([]byte, len(raw))
|
|
copy(tmp, raw)
|
|
claim = string(tmp)
|
|
}
|
|
opc, err := jwt.DecodeOperatorClaims(claim)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return opc, nil
|
|
}
|
|
|
|
// Just wipe slice with 'x', for clearing contents of nkey seed file.
|
|
func wipeSlice(buf []byte) {
|
|
for i := range buf {
|
|
buf[i] = 'x'
|
|
}
|
|
}
|
|
|
|
// validateTrustedOperators will check that we do not have conflicts with
|
|
// assigned trusted keys and trusted operators. If operators are defined we
|
|
// will expand the trusted keys in options.
|
|
func validateTrustedOperators(o *Options) error {
|
|
if len(o.TrustedOperators) == 0 {
|
|
return nil
|
|
}
|
|
if o.AllowNewAccounts {
|
|
return fmt.Errorf("operators do not allow dynamic creation of new accounts")
|
|
}
|
|
if o.AccountResolver == nil {
|
|
return fmt.Errorf("operators require an account resolver to be configured")
|
|
}
|
|
if len(o.Accounts) > 0 {
|
|
return fmt.Errorf("operators do not allow Accounts to be configured directly")
|
|
}
|
|
if len(o.Users) > 0 || len(o.Nkeys) > 0 {
|
|
return fmt.Errorf("operators do not allow users to be configured directly")
|
|
}
|
|
if len(o.TrustedOperators) > 0 && len(o.TrustedKeys) > 0 {
|
|
return fmt.Errorf("conflicting options for 'TrustedKeys' and 'TrustedOperators'")
|
|
}
|
|
// If we have operators, fill in the trusted keys.
|
|
// FIXME(dlc) - We had TrustedKeys before TrustedOperators. The jwt.OperatorClaims
|
|
// has a DidSign(). Use that longer term. For now we can expand in place.
|
|
for _, opc := range o.TrustedOperators {
|
|
if o.TrustedKeys == nil {
|
|
o.TrustedKeys = make([]string, 0, 4)
|
|
}
|
|
o.TrustedKeys = append(o.TrustedKeys, opc.Issuer)
|
|
o.TrustedKeys = append(o.TrustedKeys, opc.SigningKeys...)
|
|
}
|
|
for _, key := range o.TrustedKeys {
|
|
if !nkeys.IsValidPublicOperatorKey(key) {
|
|
return fmt.Errorf("trusted Keys %q are required to be a valid public operator nkey", key)
|
|
}
|
|
}
|
|
return nil
|
|
}
|