|  | /* | 
|  | Copyright 2017 Google Inc. | 
|  |  | 
|  | 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 adapter | 
|  |  | 
|  | import ( | 
|  | "bytes" | 
|  | "encoding/json" | 
|  | "fmt" | 
|  | "net/http" | 
|  | "net/url" | 
|  |  | 
|  | "github.com/apid/istioApigeeAdapter/adapter/config" | 
|  | "github.com/apid/istioApigeeAdapter/common" | 
|  | "istio.io/mixer/pkg/adapter" | 
|  | ) | 
|  |  | 
|  | const ( | 
|  | checkName     = "apigeeKeyChecker" | 
|  | checkDesc     = "Verify an API key from a parameter" | 
|  | verifyKeyPath = "/verifyApiKey" | 
|  | ) | 
|  |  | 
|  | var checkConf = &config.VerifyKeyParams{} | 
|  |  | 
|  | type keyCheckBuilder struct { | 
|  | adapter.DefaultBuilder | 
|  | } | 
|  |  | 
|  | type keyChecker struct { | 
|  | env      adapter.Env | 
|  | checkURL string | 
|  | } | 
|  |  | 
|  | func newKeyCheckBuilder() adapter.ListsBuilder { | 
|  | return keyCheckBuilder{ | 
|  | adapter.NewDefaultBuilder(checkName, checkDesc, checkConf), | 
|  | } | 
|  | } | 
|  |  | 
|  | func (b keyCheckBuilder) ValidateConfig(c adapter.Config) (ce *adapter.ConfigErrors) { | 
|  | cfg := c.(*config.VerifyKeyParams) | 
|  | if cfg.Organization == "" { | 
|  | ce = ce.Appendf("organization", "Organization parameter must be specified") | 
|  | } | 
|  | if cfg.Environment == "" { | 
|  | ce = ce.Appendf("environment", "Environment parameter must be specified") | 
|  | } | 
|  | if cfg.VerificationURL != "" { | 
|  | _, err := url.Parse(cfg.VerificationURL) | 
|  | if err != nil { | 
|  | ce = ce.Appendf("verificationURL", "Invalid verification URL: %s", err) | 
|  | } | 
|  | } | 
|  | return | 
|  | } | 
|  |  | 
|  | func (b keyCheckBuilder) NewListsAspect(env adapter.Env, c adapter.Config) (adapter.ListsAspect, error) { | 
|  | cfg := c.(*config.VerifyKeyParams) | 
|  | var basePath string | 
|  |  | 
|  | if cfg.VerificationURL == "" { | 
|  | basePath = fmt.Sprintf("https://%s-%s.apigee.net/edgemicro-auth", | 
|  | cfg.Organization, cfg.Environment) | 
|  | } else { | 
|  | basePath = cfg.VerificationURL | 
|  | } | 
|  |  | 
|  | kc := &keyChecker{ | 
|  | env:      env, | 
|  | checkURL: basePath + verifyKeyPath, | 
|  | } | 
|  | env.Logger().Infof("Created Apigee Key Checker to invoke \"%s\"", kc.checkURL) | 
|  |  | 
|  | return kc, nil | 
|  | } | 
|  |  | 
|  | func (l *keyChecker) Close() error { | 
|  | return nil | 
|  | } | 
|  |  | 
|  | // CheckList is part of the interface for a "list checker" adapter. It's the part that | 
|  | // gets whatever the value is (we want it to be the API key in our case) and checks it. | 
|  |  | 
|  | // Test command ./bazel-bin/cmd/client/mixc check -a target.service=f.default.svc.cluster.local --stringmap_attributes request.headers=x-api-key:1tu9pl04Srua2MtsAGtu6ViPxSYSSX2I | 
|  |  | 
|  | func (l *keyChecker) CheckList(symbol string) (bool, error) { | 
|  | apiKeyBody := common.VerifyAPIKeyRequest{ | 
|  | Key: symbol, | 
|  | } | 
|  | requestBody, _ := json.Marshal(&apiKeyBody) | 
|  |  | 
|  | resp, err := http.DefaultClient.Post(l.checkURL, "application/json", | 
|  | bytes.NewBuffer(requestBody)) | 
|  | if err != nil { | 
|  | l.env.Logger().Errorf("Error contacting verification service: %s", err) | 
|  | return false, err | 
|  | } | 
|  | defer resp.Body.Close() | 
|  |  | 
|  | if resp.StatusCode != 200 { | 
|  | return false, nil | 
|  | } else { | 
|  | return true, nil | 
|  | } | 
|  | } |