github.com/kbehouse/nsc@v0.0.6/cmd/memresolverconfigbuilder.go (about) 1 /* 2 * Copyright 2018-2019 The NATS Authors 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package cmd 17 18 import ( 19 "bytes" 20 "errors" 21 "fmt" 22 "io/ioutil" 23 "path/filepath" 24 "sort" 25 26 "github.com/kbehouse/nsc/cmd/store" 27 "github.com/nats-io/jwt/v2" 28 ) 29 30 type MemResolverConfigBuilder struct { 31 operator string 32 claims map[string]string 33 pubToName map[string]string 34 dir string 35 sysAccount string 36 } 37 38 func NewMemResolverConfigBuilder() *MemResolverConfigBuilder { 39 cb := MemResolverConfigBuilder{} 40 cb.claims = make(map[string]string) 41 cb.pubToName = make(map[string]string) 42 return &cb 43 } 44 45 func (cb *MemResolverConfigBuilder) SetOutputDir(fp string) error { 46 cb.dir = fp 47 return nil 48 } 49 50 func (cb *MemResolverConfigBuilder) SetSystemAccount(id string) error { 51 cb.sysAccount = id 52 return nil 53 } 54 55 func (cb *MemResolverConfigBuilder) Add(rawClaim []byte) error { 56 token := string(rawClaim) 57 gc, err := jwt.DecodeGeneric(token) 58 if err != nil { 59 return err 60 } 61 switch gc.ClaimType() { 62 case jwt.OperatorClaim: 63 oc, err := jwt.DecodeOperatorClaims(token) 64 if err != nil { 65 return err 66 } 67 cb.operator = token 68 cb.pubToName[oc.Subject] = oc.Name 69 cb.pubToName["__OPERATOR__"] = oc.Subject 70 case jwt.AccountClaim: 71 ac, err := jwt.DecodeAccountClaims(token) 72 if err != nil { 73 return err 74 } 75 cb.claims[ac.Subject] = token 76 cb.pubToName[ac.Subject] = ac.Name 77 } 78 return nil 79 } 80 81 func (cb *MemResolverConfigBuilder) GenerateConfig() ([]byte, error) { 82 var buf bytes.Buffer 83 84 opk := cb.pubToName["__OPERATOR__"] 85 if opk == "" { 86 return nil, errors.New("operator is not set") 87 } 88 buf.WriteString(fmt.Sprintf("// Operator %q\n", cb.pubToName[opk])) 89 buf.WriteString(fmt.Sprintf("operator: %s\n\n", cb.operator)) 90 91 if cb.sysAccount != "" { 92 buf.WriteString(fmt.Sprintf("system_account: %s\n\n", cb.sysAccount)) 93 } 94 95 var keys []string 96 for k := range cb.claims { 97 keys = append(keys, k) 98 } 99 sort.Strings(keys) 100 buf.WriteString("resolver: MEMORY\n\n") 101 buf.WriteString("resolver_preload: {\n") 102 for _, k := range keys { 103 v := cb.claims[k] 104 buf.WriteString(fmt.Sprintf(" // Account %q\n", cb.pubToName[k])) 105 buf.WriteString(fmt.Sprintf(" %s: %s\n\n", k, v)) 106 } 107 buf.WriteString("}\n") 108 return buf.Bytes(), nil 109 } 110 111 func (cb *MemResolverConfigBuilder) writeFile(dir string, name string, token string) (string, error) { 112 fp := filepath.Join(dir, store.JwtName(name)) 113 err := ioutil.WriteFile(fp, []byte(token), 0666) 114 return fp, err 115 } 116 117 func (cb *MemResolverConfigBuilder) GenerateDir() ([]byte, error) { 118 var buf bytes.Buffer 119 120 if err := MaybeMakeDir(cb.dir); err != nil { 121 return nil, err 122 } 123 124 opk := cb.pubToName["__OPERATOR__"] 125 if opk == "" { 126 return nil, errors.New("operator is not set") 127 } 128 129 fn, err := cb.writeFile(cb.dir, cb.pubToName[opk], cb.operator) 130 if err != nil { 131 return nil, err 132 } 133 buf.WriteString(fmt.Sprintf("// Operator %q\n", cb.pubToName[opk])) 134 buf.WriteString(fmt.Sprintf("operator: %q\n\n", filepath.Join(".", filepath.Base(fn)))) 135 136 if cb.sysAccount != "" { 137 buf.WriteString(fmt.Sprintf("system_account: %s\n\n", cb.sysAccount)) 138 } 139 140 var keys []string 141 for k := range cb.claims { 142 keys = append(keys, k) 143 } 144 sort.Strings(keys) 145 buf.WriteString("resolver: MEMORY\n\n") 146 buf.WriteString("resolver_preload: {\n") 147 for _, k := range keys { 148 v := cb.claims[k] 149 n := cb.pubToName[k] 150 buf.WriteString(fmt.Sprintf(" // Account %q\n", n)) 151 fn, err := cb.writeFile(cb.dir, n, v) 152 if err != nil { 153 return nil, err 154 } 155 rel, err := filepath.Rel(cb.dir, fn) 156 if err != nil { 157 return nil, err 158 } 159 buf.WriteString(fmt.Sprintf(" %s: %q\n\n", k, rel)) 160 } 161 buf.WriteString("}\n") 162 163 err = ioutil.WriteFile(filepath.Join(cb.dir, "resolver.conf"), buf.Bytes(), 0666) 164 if err != nil { 165 return nil, err 166 } 167 168 return nil, nil 169 } 170 171 func (cb *MemResolverConfigBuilder) Generate() ([]byte, error) { 172 if cb.dir != "" { 173 return cb.GenerateDir() 174 } 175 return cb.GenerateConfig() 176 }