Skip to content

Commit

Permalink
Merge pull request #6 from coreos-inc/credstore
Browse files Browse the repository at this point in the history
Create the credential store registration mechanism and wire it in
  • Loading branch information
Jake Moshenko committed Mar 9, 2016
2 parents 90ace5f + fa768cc commit 0a67742
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 78 deletions.
24 changes: 14 additions & 10 deletions cmd/hmacproxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ package main

import (
"flag"
log "github.com/Sirupsen/logrus"
"github.com/coreos-inc/hmacproxy"
"github.com/coreos-inc/hmacproxy/config"
"net/http/httptest"
"net/url"
"os"

log "github.com/Sirupsen/logrus"

"github.com/coreos-inc/hmacproxy"
"github.com/coreos-inc/hmacproxy/config"
"github.com/coreos-inc/hmacproxy/credential"
_ "github.com/coreos-inc/hmacproxy/credential/singlekey"
)

func main() {
Expand All @@ -47,7 +51,7 @@ func main() {
if proxyConfig.Signer != nil {
log.Infof("Starting signing proxy on: %s", proxyConfig.Signer.ListenerAddr)

signingCredential := hmacproxy.SingleAccessKey{
signingCredential := credential.Credential{
proxyConfig.Signer.Key.ID,
proxyConfig.Signer.Key.Secret,
proxyConfig.Signer.Key.Service,
Expand All @@ -73,13 +77,13 @@ func main() {
proxyConfig.Verifier.ListenerAddr,
proxyConfig.Verifier.Upstream,
)
tmpCred := hmacproxy.SingleAccessKey{
proxyConfig.Signer.Key.ID,
proxyConfig.Signer.Key.Secret,
proxyConfig.Signer.Key.Service,
proxyConfig.Signer.Key.Region,

cs, err := credential.CreateCredentialStore(proxyConfig.Verifier.CredentialSource)
if err != nil {
log.Fatal(err)
}
verificationProxy, err := hmacproxy.CreateVerifyingProxy(proxyConfig.Verifier.Upstream.URL, tmpCred)

verificationProxy, err := hmacproxy.CreateVerifyingProxy(proxyConfig.Verifier.Upstream.URL, cs)
if err != nil {
log.Fatal(err)
}
Expand Down
3 changes: 2 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ package config

import (
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"net/url"
"os"
"time"

"gopkg.in/yaml.v2"
)

// URL is a custom URL type that allows validation at configuration load time.
Expand Down
22 changes: 22 additions & 0 deletions credential/credential.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2016 CoreOS, 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 credential

type Credential struct {
ID string
Secret string
Service string
Region string
}
52 changes: 52 additions & 0 deletions credential/singlekey/singlekey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2016 CoreOS, 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 singlekey

import (
"fmt"

"gopkg.in/yaml.v2"

"github.com/coreos-inc/hmacproxy/config"
"github.com/coreos-inc/hmacproxy/credential"
)

type SingleAccessKey struct {
credential.Credential
}

func (s SingleAccessKey) LoadCredential(keyID, serviceName, regionName string) (*credential.Credential, error) {
if keyID != s.ID || serviceName != s.Service || regionName != s.Region {
return nil, fmt.Errorf("Unknown key with key id: %s", keyID)
}
return &s.Credential, nil
}

func constructor(cfg *config.CredentialSourceConfig) (credential.CredentialStore, error) {
reserialized, err := yaml.Marshal(cfg.Options)
if err != nil {
return nil, fmt.Errorf("unable to marshall configuration: %v", cfg.Options)
}
var parsed SingleAccessKey
err = yaml.Unmarshal(reserialized, &parsed)
if err != nil {
return nil, fmt.Errorf("unable to parse configuration: %v", reserialized)
}
return parsed, nil
}

func init() {
credential.RegisterCredentialStoreFacory("SingleCredential", constructor)
}
59 changes: 59 additions & 0 deletions credential/store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2016 CoreOS, 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 credential

import (
"fmt"

"github.com/coreos-inc/hmacproxy/config"
)

type CredentialStoreConstructor func(*config.CredentialSourceConfig) (CredentialStore, error)

var storeFactories = make(map[string]CredentialStoreConstructor)

// RegisterNotifier makes a Fetcher available by the provided name.
// If Register is called twice with the same name or if driver is nil,
// it panics.
func RegisterCredentialStoreFacory(name string, csf func(*config.CredentialSourceConfig) (CredentialStore, error)) {
if name == "" {
panic("credentials: could not register a CredentialStore with an empty name")
}

if csf == nil {
panic("credentials: could not register a nil CredentialStore")
}

if _, dup := storeFactories[name]; dup {
panic("credentials: RegisterCredentialStore called twice for " + name)
}

storeFactories[name] = csf
}

func CreateCredentialStore(cfg *config.CredentialSourceConfig) (cs CredentialStore, err error) {
constructor, found := storeFactories[cfg.Type]
if !found {
err = fmt.Errorf("credentials: Unable to find credential store constructor for %s", cfg.Type)
return
}

cs, err = constructor(cfg)
return
}

type CredentialStore interface {
LoadCredential(keyID, serviceName, regionName string) (*Credential, error)
}
60 changes: 0 additions & 60 deletions credentials.go

This file was deleted.

6 changes: 4 additions & 2 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ import (
"net/http"
"net/http/httputil"
"net/url"

"github.com/coreos-inc/hmacproxy/credential"
)

func CreateSigningProxy(target *url.URL, credential Credential) (*httputil.ReverseProxy, error) {
func CreateSigningProxy(target *url.URL, cred credential.Credential) (*httputil.ReverseProxy, error) {
director := func(req *http.Request) {
log.Printf("Proxying request %v", req)
req.URL.Scheme = target.Scheme
Expand All @@ -30,7 +32,7 @@ func CreateSigningProxy(target *url.URL, credential Credential) (*httputil.Rever
return &httputil.ReverseProxy{Director: director}, nil
}

func CreateVerifyingProxy(target *url.URL, credStore CredentialStore) (*httputil.ReverseProxy, error) {
func CreateVerifyingProxy(target *url.URL, cs credential.CredentialStore) (*httputil.ReverseProxy, error) {
director := func(req *http.Request) {
log.Printf("Proxying request %v", req)
req.URL.Scheme = target.Scheme
Expand Down
11 changes: 6 additions & 5 deletions hmac_v4.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/signer/v4"

"github.com/coreos-inc/hmacproxy/credential"
)

// timeFormat is the format used in the X-Amz-Date header with aws-sdk-go.
Expand Down Expand Up @@ -63,7 +65,7 @@ var (

// Sign4 signs the given http.Request using AWS-Style HMAC v4
// with the specified Credential, region and service names.
func Sign4(req *http.Request, cred Credential, regionName, serviceName string) error {
func Sign4(req *http.Request, cred credential.Credential) error {
// If the request that we need to sign has a Body, we must read it entirely and convert it into a
// ReadSeeker in order to sign the request.
if req.Body != nil {
Expand All @@ -76,16 +78,15 @@ func Sign4(req *http.Request, cred Credential, regionName, serviceName string) e
}

// Sign the given http.Request.
return sign(req, cred.KeyID(), cred.KeySecret(), regionName, serviceName,
time.Now().UTC())
return sign(req, cred.ID, cred.Secret, cred.Region, cred.Service, time.Now().UTC())
}

// Verify4 verifies the AWS-Style HMAC v4 signature present in the given http.Request.
// It uses the CredentialStore to find the appropriate Credential based on the key ID, region and
// service names. The maxSkew duration represents the time window within a signed request stays
// valid. Verify4 returns true if the http.Request has been verified successfully, otherwise
// the returned error contains the failure reason.
func Verify4(req *http.Request, creds CredentialStore, maxSkew time.Duration) (bool, error) {
func Verify4(req *http.Request, creds credential.CredentialStore, maxSkew time.Duration) (bool, error) {
// Shallow copy the request as we're going to modify its headers,
// and make its Body a ReadSeekerCloser as AWS going to read it and http.Request must be able to
// Close() it.
Expand Down Expand Up @@ -124,7 +125,7 @@ func Verify4(req *http.Request, creds CredentialStore, maxSkew time.Duration) (b
}

// Sign our copy of the given http.Request.
err = sign(reqCopy, keyID, cred.KeySecret(), regionName, serviceName, signatureTime)
err = sign(reqCopy, keyID, cred.Secret, regionName, serviceName, signatureTime)
if err != nil {
return false, err
}
Expand Down

0 comments on commit 0a67742

Please sign in to comment.