Move code from our old branch to this one.
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..921dbe8 --- /dev/null +++ b/.gitignore
@@ -0,0 +1,8 @@ +bazel-bin +bazel-genfiles +bazel-istioApigeeAdapter +bazel-out +bazel-testlogs +*.pb.go + +
diff --git a/BUILD b/BUILD new file mode 100644 index 0000000..0aa7eec --- /dev/null +++ b/BUILD
@@ -0,0 +1,7 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load("@io_bazel_rules_go//go:def.bzl", "go_prefix") + +go_prefix("github.com/apid/istioApigeeAdapter")
diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 0000000..9f076a0 --- /dev/null +++ b/WORKSPACE
@@ -0,0 +1,60 @@ +workspace(name = "com_github_apid_apigeeIstioAdapter") + +git_repository( + name = "io_bazel_rules_go", + commit = "87cdda3fc0fd65c63ef0316533be03ea4956f809", + remote = "https://github.com/bazelbuild/rules_go.git", +) + +load("@io_bazel_rules_go//go:def.bzl", "go_repositories", "new_go_repository") +go_repositories() + +git_repository( + name = "io_istio_mixer", + commit = "5bae502af7492b59d0a59d7f2e89bd95d1088efe", + remote = "https://github.com/istio/mixer.git", +) + +# Replace the above with the below to build with your own local copy of mixer +#local_repository( +# name = "io_istio_mixer", +# path = "PATH_TO_MIXER_CODE_ON_YOUR_BOX", +#) + +git_repository( + name = "org_pubref_rules_protobuf", + commit = "9ede1dbc38f0b89ae6cd8e206a22dd93cc1d5637", + remote = "https://github.com/pubref/rules_protobuf", +) +load("@org_pubref_rules_protobuf//protobuf:rules.bzl", "proto_repositories") + +proto_repositories() + +load("@org_pubref_rules_protobuf//gogo:rules.bzl", "gogo_proto_repositories") + +gogo_proto_repositories() + +new_go_repository( + name = "com_github_golang_protobuf", + commit = "8ee79997227bf9b34611aee7946ae64735e6fd93", + importpath = "github.com/golang/protobuf", +) + +new_go_repository( + name = "com_github_hashicorp_go_multierror", + commit = "ed905158d87462226a13fe39ddf685ea65f1c11f", + importpath = "github.com/hashicorp/go-multierror", +) + +new_go_repository( + name = "com_github_hashicorp_errwrap", + commit = "7554cd9344cec97297fa6649b055a8c98c2a1e55", + importpath = "github.com/hashicorp/errwrap", +) + +new_git_repository( + name = "com_github_googleapis_googleapis", + build_file = "bazel/BUILD.googleapis", + commit = "13ac2436c5e3d568bd0e938f6ed58b77a48aba15", + remote = "https://github.com/googleapis/googleapis.git", +) \ No newline at end of file
diff --git a/adapter/BUILD b/adapter/BUILD new file mode 100644 index 0000000..cde5ace --- /dev/null +++ b/adapter/BUILD
@@ -0,0 +1,25 @@ +package(default_visibility = ["//visibility:public"]) + +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "apigee.go", + "apigeeKeyChecker.go", + "apigeeReport.go", + ], + deps = [ + "//adapter/config:go_default_library", + "@com_github_hashicorp_go_multierror//:go_default_library", + "@io_istio_mixer//pkg/adapter:go_default_library", + ], +) + +go_test( + name = "small_tests", + size = "small", + srcs = ["apigeeKeyChecker_test.go"], + library = ":go_default_library", + deps = [], +)
diff --git a/adapter/apigee.go b/adapter/apigee.go new file mode 100644 index 0000000..cddcfb1 --- /dev/null +++ b/adapter/apigee.go
@@ -0,0 +1,27 @@ +// Copyright 2017 Istio 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 apigee + +import ( + "istio.io/mixer/pkg/adapter" +) + +// Register records the builders exposed by this adapter. +// For the apigee adapter, we will eventually expose multiple builders, each for a different +// aspect of the Apigee functionality. +func Register(r adapter.Registrar) { + r.RegisterListsBuilder(newKeyCheckBuilder()) + r.RegisterAccessLogsBuilder(newReportBuilder()) +}
diff --git a/adapter/apigeeKeyChecker.go b/adapter/apigeeKeyChecker.go new file mode 100644 index 0000000..3aeeaf8 --- /dev/null +++ b/adapter/apigeeKeyChecker.go
@@ -0,0 +1,100 @@ +// Copyright 2017 Istio 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 apigee + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + + "github.com/apid/istioApigeeAdapter/adapter/config" + "istio.io/mixer/pkg/adapter" +) + +const ( + checkName = "apigeeKeyChecker" + checkDesc = "Verify an API key from a parameter" +) + +var checkConf = &config.VerifyKeyParams{} + +type keyCheckBuilder struct { + adapter.DefaultBuilder +} + +type keyChecker struct { + keyParam string + organization string + environment string +} + +type APIKeyBody struct { + APIKey string `json:"apiKey"` +} + +func newKeyCheckBuilder() keyCheckBuilder { + return keyCheckBuilder{ + adapter.NewDefaultBuilder(checkName, checkDesc, checkConf), + } +} + +func (keyCheckBuilder) NewListsAspect(env adapter.Env, c adapter.Config) (adapter.ListsAspect, error) { + return newKeyChecker(c.(*config.VerifyKeyParams)) +} + +func newKeyChecker(c *config.VerifyKeyParams) (*keyChecker, error) { + return &keyChecker{ + keyParam: c.KeyParameter, + organization: c.Organization, + environment: c.Environment, + }, 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) { + fmt.Printf("*** Going to check \"%s\" against \"%s\"\n", symbol, l.organization) + + edge_url := "https://" + l.organization + "-" + l.environment + ".apigee.net/edgemicro-auth/verifyApiKey" + + fmt.Printf("*** edge_url \"%s\"\n", edge_url) + + return verifyApiKey(symbol, edge_url), nil +} + +func verifyApiKey(apiKey string, uri string) bool { + apiKeyBody := APIKeyBody{ + APIKey: apiKey, + } + serializedBody, _ := json.Marshal(&apiKeyBody) + req, _ := http.NewRequest("POST", uri, bytes.NewBuffer(serializedBody)) + req.Header.Add("x-dna-api-key", apiKey) + req.Header.Add("content-type", "application/json") + client := &http.Client{} + resp, _ := client.Do(req) + if resp.StatusCode != 200 { + return false + } else { + return true + } +}
diff --git a/adapter/apigeeKeyChecker_test.go b/adapter/apigeeKeyChecker_test.go new file mode 100644 index 0000000..b4a2f26 --- /dev/null +++ b/adapter/apigeeKeyChecker_test.go
@@ -0,0 +1,2 @@ +package apigee +
diff --git a/adapter/apigeeReport.go b/adapter/apigeeReport.go new file mode 100644 index 0000000..7caa87c --- /dev/null +++ b/adapter/apigeeReport.go
@@ -0,0 +1,131 @@ +package apigee + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "os" + + "github.com/apid/istioApigeeAdapter/adapter/config" + me "github.com/hashicorp/go-multierror" + "istio.io/mixer/pkg/adapter" +) + +type ( + builder struct{ adapter.DefaultBuilder } + + logger struct{ logStream io.Writer } + + analyticsRecord struct { + ClientReceivedStartTimestamp int `json:"client_received_start_timestamp"` + ClientReceivedEndTimestamp int `json:"client_received_end_timestamp"` + RecordType string `json:"recordType"` + ApiProxy string `json:"apiproxy"` + RequestUri string `json:"request_uri"` + RequestPath string `json:"request_path"` + RequestVerb string `json:"request_verb"` + ClientIp string `json:"request_path"` + UserAgent string `json:"useragent"` + ApiProxyRevision string `json:"apiproxy_revision"` + ResponseStatusCode int `json:"response_status_code"` + ClientSentStartTimestamp int `json:"client_sent_start_timestamp"` + ClientSentEndTimestamp int `json:"client_sent_end_timestamp"` + DeveloperEmail string `json:"developer_email,omitempty"` + DeveloperApp string `json:"developer_app"` + AccessToken string `json:"access_token,omitempty"` + ClientId string `json:"client_id,omitempty"` + ApiProduct string `json:"api_product"` + } + + analyticsRecordCollection struct { + Records []analyticsRecord `json:"records"` + } + + edgemicroKeys struct { + Key string + Secret string + } +) + +func newReportBuilder() builder { + return builder{adapter.NewDefaultBuilder( + "apigeeReport", + "Report logs to apigee", + &config.ReportParams{}, + )} +} + +func (builder) NewApplicationLogsAspect(env adapter.Env, cfg adapter.Config) (adapter.ApplicationLogsAspect, error) { + return newLogger(cfg) +} + +func (builder) NewAccessLogsAspect(env adapter.Env, cfg adapter.Config) (adapter.AccessLogsAspect, error) { + return newLogger(cfg) +} + +func newLogger(cfg adapter.Config) (*logger, error) { + c := cfg.(*config.ReportParams) + + w := os.Stderr + if c.LogStream == config.STDOUT { + w = os.Stdout + } + + return &logger{w}, nil +} + +func (l *logger) Log(entries []adapter.LogEntry) error { + return l.log(entries) +} + +func (l *logger) LogAccess(entries []adapter.LogEntry) error { + fmt.Println("*** here") + return l.log(entries) +} + +func (l *logger) log(entries []adapter.LogEntry) error { + var recordsCollection []analyticsRecord + + var errors *me.Error + for _, entry := range entries { + + if err := writeJSON(l.logStream, entry); err != nil { + errors = me.Append(errors, err) + } + + ax_data := analyticsRecord{ + ClientReceivedStartTimestamp: 33, + DeveloperApp: "microgateway-demo", + } + + recordsCollection = append(recordsCollection, ax_data) + + } + + res2B, _ := json.Marshal(recordsCollection) + fmt.Println(string(res2B)) + + return errors.ErrorOrNil() +} + +func (l *logger) Close() error { return nil } + +func writeJSON(w io.Writer, le interface{}) error { + return json.NewEncoder(w).Encode(le) +} + +func sendAnalyticsRecords(collection analyticsRecordCollection, keys edgemicroKeys, uri string) bool { + serializedBody, _ := json.Marshal(&collection) + req, _ := http.NewRequest("POST", uri, bytes.NewBuffer(serializedBody)) + req.SetBasicAuth(keys.Key, keys.Secret) + req.Header.Add("content-type", "application/json") + client := &http.Client{} + resp, _ := client.Do(req) + if resp.StatusCode != 200 { + return false + } else { + return true + } +}
diff --git a/adapter/config/BUILD b/adapter/config/BUILD new file mode 100644 index 0000000..cdde8c7 --- /dev/null +++ b/adapter/config/BUILD
@@ -0,0 +1,26 @@ +package(default_visibility = ["//visibility:public"]) + +load("@org_pubref_rules_protobuf//gogo:rules.bzl", "gogoslick_proto_library") + +gogoslick_proto_library( + name = "go_default_library", + importmap = { + "gogoproto/gogo.proto": "github.com/gogo/protobuf/gogoproto", + }, + imports = [ + "external/com_github_gogo_protobuf", + "external/com_github_google_protobuf/src", + ], + inputs = [ + "@com_github_google_protobuf//:well_known_protos", + "@com_github_gogo_protobuf//gogoproto:go_default_library_protos", + ], + protos = [ + "config.proto", + ], + verbose = 0, + visibility = ["//adapter:__pkg__"], + deps = [ + "@com_github_gogo_protobuf//gogoproto:go_default_library", + ], +)
diff --git a/adapter/config/config.proto b/adapter/config/config.proto new file mode 100644 index 0000000..6c3c680 --- /dev/null +++ b/adapter/config/config.proto
@@ -0,0 +1,56 @@ +// Copyright 2017 Istio 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. + +syntax = "proto3"; + +package adapter.apigee.config; + +import "gogoproto/gogo.proto"; + +option go_package="config"; +option (gogoproto.goproto_getters_all) = false; +option (gogoproto.equal_all) = false; +option (gogoproto.gostring_all) = false; + +message VerifyKeyParams { + // The name of the parameter where the API key is stored. + string key_parameter = 1; + + string organization = 2; + + string environment = 3; +} + +message ReportParams { + + // Stream is used to select between different logs output sinks. + enum Stream { + // STDERR refers to os.Stderr. + STDERR = 0; + // STDOUT refers to os.Stdout. + STDOUT = 1; + } + + // Selects which standard stream to write to for log entries. + // STDERR is the default Stream. + Stream log_stream = 1; + + string organization = 2; + + string environment = 3; + + string key = 4; + + string secret = 5; +}
diff --git a/bazel/BUILD.googleapis b/bazel/BUILD.googleapis new file mode 100644 index 0000000..bf13dbe --- /dev/null +++ b/bazel/BUILD.googleapis
@@ -0,0 +1,52 @@ +package(default_visibility = ["//visibility:public"]) + +load("@io_bazel_rules_go//go:def.bzl", "go_prefix") +go_prefix("github.com/googleapis/googleapis") + +load("@org_pubref_rules_protobuf//gogo:rules.bzl", "gogoslick_proto_library") + +gogoslick_proto_library( + name = "google/rpc", + protos = [ + "google/rpc/code.proto", + "google/rpc/error_details.proto", + "google/rpc/status.proto", + ], + importmap = { + "google/protobuf/any.proto": "github.com/gogo/protobuf/types", + "google/protobuf/duration.proto": "github.com/gogo/protobuf/types", + }, + imports = [ + "../../external/com_github_google_protobuf/src", + ], + inputs = [ + "@com_github_google_protobuf//:well_known_protos", + ], + deps = [ + "@com_github_gogo_protobuf//types:go_default_library", + ], + verbose = 0, +) + +load("@org_pubref_rules_protobuf//cpp:rules.bzl", "cc_proto_library") + +cc_proto_library( + name = "cc_status_proto", + protos = [ + "google/rpc/status.proto", + ], + imports = [ + "../../external/com_github_google_protobuf/src", + ], + verbose = 0, +) + +filegroup( + name = "status_proto", + srcs = [ "google/rpc/status.proto" ], +) + +filegroup( + name = "code_proto", + srcs = [ "google/rpc/code.proto" ], +)