github.com/blixtra/rkt@v0.8.1-0.20160204105720-ab0d1add1a43/rkt/config/auth.go (about) 1 // Copyright 2015 The rkt Authors 2 // 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 package config 16 17 import ( 18 "encoding/base64" 19 "encoding/json" 20 "fmt" 21 "net/http" 22 ) 23 24 const ( 25 authHeader string = "Authorization" 26 ) 27 28 type authV1JsonParser struct{} 29 30 type authV1 struct { 31 Domains []string `json:"domains"` 32 Type string `json:"type"` 33 Credentials json.RawMessage `json:"credentials"` 34 } 35 36 type basicV1 struct { 37 User string `json:"user"` 38 Password string `json:"password"` 39 } 40 41 type oauthV1 struct { 42 Token string `json:"token"` 43 } 44 45 type dockerAuthV1JsonParser struct{} 46 47 type dockerAuthV1 struct { 48 Registries []string `json:"registries"` 49 Credentials basicV1 `json:"credentials"` 50 } 51 52 func init() { 53 addParser("auth", "v1", &authV1JsonParser{}) 54 addParser("dockerAuth", "v1", &dockerAuthV1JsonParser{}) 55 registerSubDir("auth.d", []string{"auth", "dockerAuth"}) 56 } 57 58 type basicAuthHeaderer struct { 59 user string 60 password string 61 } 62 63 func (h *basicAuthHeaderer) Header() http.Header { 64 headers := make(http.Header) 65 creds := []byte(fmt.Sprintf("%s:%s", h.user, h.password)) 66 encodedCreds := base64.StdEncoding.EncodeToString(creds) 67 headers.Add(authHeader, "Basic "+encodedCreds) 68 69 return headers 70 } 71 72 type oAuthBearerTokenHeaderer struct { 73 token string 74 } 75 76 func (h *oAuthBearerTokenHeaderer) Header() http.Header { 77 headers := make(http.Header) 78 headers.Add(authHeader, "Bearer "+h.token) 79 80 return headers 81 } 82 83 func (p *authV1JsonParser) parse(config *Config, raw []byte) error { 84 var auth authV1 85 if err := json.Unmarshal(raw, &auth); err != nil { 86 return err 87 } 88 if len(auth.Domains) == 0 { 89 return fmt.Errorf("no domains specified") 90 } 91 if len(auth.Type) == 0 { 92 return fmt.Errorf("no auth type specified") 93 } 94 var ( 95 err error 96 headerer Headerer 97 ) 98 switch auth.Type { 99 case "basic": 100 headerer, err = p.getBasicV1Headerer(auth.Credentials) 101 case "oauth": 102 headerer, err = p.getOAuthV1Headerer(auth.Credentials) 103 default: 104 err = fmt.Errorf("unknown auth type: %q", auth.Type) 105 } 106 if err != nil { 107 return err 108 } 109 for _, domain := range auth.Domains { 110 if _, ok := config.AuthPerHost[domain]; ok { 111 return fmt.Errorf("auth for domain %q is already specified", domain) 112 } 113 config.AuthPerHost[domain] = headerer 114 } 115 return nil 116 } 117 118 func (p *authV1JsonParser) getBasicV1Headerer(raw json.RawMessage) (Headerer, error) { 119 var basic basicV1 120 if err := json.Unmarshal(raw, &basic); err != nil { 121 return nil, err 122 } 123 if err := validateBasicV1(&basic); err != nil { 124 return nil, err 125 } 126 return &basicAuthHeaderer{ 127 user: basic.User, 128 password: basic.Password, 129 }, nil 130 } 131 132 func (p *authV1JsonParser) getOAuthV1Headerer(raw json.RawMessage) (Headerer, error) { 133 var oauth oauthV1 134 if err := json.Unmarshal(raw, &oauth); err != nil { 135 return nil, err 136 } 137 if len(oauth.Token) == 0 { 138 return nil, fmt.Errorf("no oauth bearer token specified") 139 } 140 return &oAuthBearerTokenHeaderer{ 141 token: oauth.Token, 142 }, nil 143 } 144 145 func (p *dockerAuthV1JsonParser) parse(config *Config, raw []byte) error { 146 var auth dockerAuthV1 147 if err := json.Unmarshal(raw, &auth); err != nil { 148 return err 149 } 150 if len(auth.Registries) == 0 { 151 return fmt.Errorf("no registries specified") 152 } 153 if err := validateBasicV1(&auth.Credentials); err != nil { 154 return err 155 } 156 basic := BasicCredentials{ 157 User: auth.Credentials.User, 158 Password: auth.Credentials.Password, 159 } 160 for _, registry := range auth.Registries { 161 if _, ok := config.DockerCredentialsPerRegistry[registry]; ok { 162 return fmt.Errorf("credentials for docker registry %q are already specified", registry) 163 } 164 config.DockerCredentialsPerRegistry[registry] = basic 165 } 166 return nil 167 } 168 169 func validateBasicV1(basic *basicV1) error { 170 if basic == nil { 171 return fmt.Errorf("no credentials") 172 } 173 if len(basic.User) == 0 { 174 return fmt.Errorf("user not specified") 175 } 176 if len(basic.Password) == 0 { 177 return fmt.Errorf("password not specified") 178 } 179 return nil 180 }