Skip to content
Snippets Groups Projects
Commit a356aab1 authored by Niall Sheridan's avatar Niall Sheridan Committed by GitHub
Browse files

Merge branch 'master' into no-datastore

parents e35249bf 10dfd241
Branches
No related tags found
No related merge requests found
...@@ -2,8 +2,8 @@ config.json ...@@ -2,8 +2,8 @@ config.json
cashierd.conf cashierd.conf
tmp tmp
cashier /cashier
cashierd /cashierd
signing_key signing_key
http.log http.log
...@@ -6,13 +6,12 @@ env: ...@@ -6,13 +6,12 @@ env:
- MYSQL_TEST="true" - MYSQL_TEST="true"
go: go:
- 1.7.4 - 1.7.5
- 1.8rc2 - 1.8rc3
- tip
matrix: matrix:
allow_failures: allow_failures:
- go: tip - go: 1.8rc2
before_install: before_install:
- go get -v github.com/golang/lint/golint - go get -v github.com/golang/lint/golint
...@@ -25,8 +24,4 @@ before_script: ...@@ -25,8 +24,4 @@ before_script:
sudo: false sudo: false
script: script:
- go install -v ./cmd/cashier ./cmd/cashierd - ./run_tests.sh
- go list ./... |grep -v vendor/ |xargs go test
- gofmt -d $(find -type f -name '*.go' -not -path './vendor/*')
- go list ./... |grep -v vendor/ |xargs go vet
- go list ./... |grep -v vendor/ |xargs -L1 golint -set_exit_status
...@@ -144,7 +144,7 @@ server { ...@@ -144,7 +144,7 @@ server {
} }
``` ```
Prior to using MySQL or SQLite you need to create the database and tables using [one of the provided files](db). Prior to using MySQL or SQLite you need to create the database and tables using [the provided seed file](db/seed.sql).
e.g. `mysql < db/seed.sql`. e.g. `mysql < db/seed.sql`.
Obviously you should setup a role user for running in prodution. Obviously you should setup a role user for running in prodution.
...@@ -216,15 +216,30 @@ For the server you need the following: ...@@ -216,15 +216,30 @@ For the server you need the following:
Once the server is up and running you'll need to configure your client. Once the server is up and running you'll need to configure your client.
The client is configured using either a [HCL](https://github.com/hashicorp/hcl) configuration file - [example](example-client.conf) - or command-line flags. The client is configured using either a [HCL](https://github.com/hashicorp/hcl) configuration file - [example](example-client.conf) - or command-line flags.
- `--ca` CA server (default "http://localhost:10000").
- `--config` Path to config file (default "~/.cashier.conf").
- `--key_size` Key size. Ignored for ed25519 keys (default 2048).
- `--key_type` Type of private key to generate - rsa, ecdsa or ed25519 (default "rsa").
- `--public_file_prefix` Prefix for filename for public key and cert (optional, no default). The public key is put in a file with `.pub` appended to it; the public cert file in a file with `-cert.pub` appended to it.
- `--validity` Key validity (default 24h).
Running the `cashier` cli tool will open a browser window at the configured CA address. Running the `cashier` cli tool will open a browser window at the configured CA address.
The CA will redirect to the auth provider for authorisation, and redirect back to the CA where the access token will printed. The CA will redirect to the auth provider for authorisation, and redirect back to the CA where the access token will printed.
Copy the access token. In the terminal where you ran the `cashier` cli paste the token at the prompt. Copy the access token. In the terminal where you ran the `cashier` cli paste the token at the prompt.
The client will then generate a new ssh key-pair and send the public part to the server (along with the access token). The client will then generate a new ssh key-pair and send the public part to the server (along with the access token).
Once signed the client will install the key and signed certificate in your ssh agent. When the certificate expires it will be removed automatically from the agent. Once signed the client will install the key and signed certificate in your ssh agent. When the certificate expires it will be removed automatically from the agent.
If you set `public_file_prefix` then the public key and public cert will be written to the files that start with `public_file_prefix` and end with `.pub` and `-cert.pub` respectively.
In your `ssh_config` you can load these for a given host with the `IdentityFile` and `CertificateFile`. However prior to OpenSSH version 7.2p1 the latter option didn't exist.
In that case you could specify `~/.ssh/some-identity` as your `IdentityFile` and OpenSSH would look in `~/.ssh/some-identity.pub` and `~/.ssh/some-identity-cert.pub`.
Starting with 7.2p1 the two options exist in the `ssh_config` and you'll need to use the full paths to them.
Note that like these `ssh_config` options, the `public_file_prefix` supports tilde expansion.
## Configuring SSH ## Configuring SSH
The ssh client needs no special configuration, just a running ssh-agent. The ssh client needs no special configuration, just a running `ssh-agent`.
The ssh server needs to trust the public part of the CA signing key. Add something like the following to your sshd_config: The ssh server needs to trust the public part of the CA signing key. Add something like the following to your `sshd_config`:
``` ```
TrustedUserCAKeys /etc/ssh/ca.pub TrustedUserCAKeys /etc/ssh/ca.pub
``` ```
......
...@@ -3,8 +3,10 @@ package client ...@@ -3,8 +3,10 @@ package client
import ( import (
"bytes" "bytes"
"crypto/tls" "crypto/tls"
"encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"path" "path"
...@@ -16,6 +18,22 @@ import ( ...@@ -16,6 +18,22 @@ import (
"golang.org/x/crypto/ssh/agent" "golang.org/x/crypto/ssh/agent"
) )
// SavePublicFiles installs the public part of the cert and key.
func SavePublicFiles(prefix string, cert *ssh.Certificate, pub ssh.PublicKey) error {
if prefix == "" {
return nil
}
pubTxt := ssh.MarshalAuthorizedKey(pub)
certPubTxt := []byte(cert.Type() + " " + base64.StdEncoding.EncodeToString(cert.Marshal()))
if err := ioutil.WriteFile(prefix+".pub", pubTxt, 0644); err != nil {
return err
}
err := ioutil.WriteFile(prefix+"-cert.pub", certPubTxt, 0644)
return err
}
// InstallCert adds the private key and signed certificate to the ssh agent. // InstallCert adds the private key and signed certificate to the ssh agent.
func InstallCert(a agent.Agent, cert *ssh.Certificate, key Key) error { func InstallCert(a agent.Agent, cert *ssh.Certificate, key Key) error {
t := time.Unix(int64(cert.ValidBefore), 0) t := time.Unix(int64(cert.ValidBefore), 0)
......
package client package client
import ( import (
"github.com/mitchellh/go-homedir"
"github.com/spf13/pflag" "github.com/spf13/pflag"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
...@@ -12,6 +13,7 @@ type Config struct { ...@@ -12,6 +13,7 @@ type Config struct {
Keysize int `mapstructure:"key_size"` Keysize int `mapstructure:"key_size"`
Validity string `mapstructure:"validity"` Validity string `mapstructure:"validity"`
ValidateTLSCertificate bool `mapstructure:"validate_tls_certificate"` ValidateTLSCertificate bool `mapstructure:"validate_tls_certificate"`
PublicFilePrefix string `mapstructure:"public_file_prefix"`
} }
func setDefaults() { func setDefaults() {
...@@ -19,6 +21,7 @@ func setDefaults() { ...@@ -19,6 +21,7 @@ func setDefaults() {
viper.BindPFlag("key_type", pflag.Lookup("key_type")) viper.BindPFlag("key_type", pflag.Lookup("key_type"))
viper.BindPFlag("key_size", pflag.Lookup("key_size")) viper.BindPFlag("key_size", pflag.Lookup("key_size"))
viper.BindPFlag("validity", pflag.Lookup("validity")) viper.BindPFlag("validity", pflag.Lookup("validity"))
viper.BindPFlag("public_file_prefix", pflag.Lookup("public_file_prefix"))
viper.SetDefault("validateTLSCertificate", true) viper.SetDefault("validateTLSCertificate", true)
} }
...@@ -34,5 +37,10 @@ func ReadConfig(path string) (*Config, error) { ...@@ -34,5 +37,10 @@ func ReadConfig(path string) (*Config, error) {
if err := viper.Unmarshal(c); err != nil { if err := viper.Unmarshal(c); err != nil {
return nil, err return nil, err
} }
p, err := homedir.Expand(c.PublicFilePrefix)
if err != nil {
return nil, err
}
c.PublicFilePrefix = p
return c, nil return c, nil
} }
...@@ -22,6 +22,7 @@ var ( ...@@ -22,6 +22,7 @@ var (
keysize = pflag.Int("key_size", 2048, "Key size. Ignored for ed25519 keys") keysize = pflag.Int("key_size", 2048, "Key size. Ignored for ed25519 keys")
validity = pflag.Duration("validity", time.Hour*24, "Key validity") validity = pflag.Duration("validity", time.Hour*24, "Key validity")
keytype = pflag.String("key_type", "rsa", "Type of private key to generate - rsa, ecdsa or ed25519") keytype = pflag.String("key_type", "rsa", "Type of private key to generate - rsa, ecdsa or ed25519")
publicFilePrefix = pflag.String("public_file_prefix", "", "Prefix for filename for public key and cert (optional, no default)")
) )
func main() { func main() {
...@@ -58,5 +59,8 @@ func main() { ...@@ -58,5 +59,8 @@ func main() {
if err := client.InstallCert(a, cert, priv); err != nil { if err := client.InstallCert(a, cert, priv); err != nil {
log.Fatalln(err) log.Fatalln(err)
} }
if err := client.SavePublicFiles(c.PublicFilePrefix, cert, pub); err != nil {
log.Fatalln(err)
}
fmt.Println("Credentials added.") fmt.Println("Credentials added.")
} }
#! /bin/sh
# This can be used as a pre-commit script. Just run
# cp run_tests.sh .git/hooks/pre-commit
# and it will run before each commit.
set -xue
go install -v ./cmd/cashier ./cmd/cashierd
go list ./... |grep -v vendor/ |xargs go test
gofmt -d $(find * -type f -name '*.go' -not -path 'vendor/*')
go list ./... |grep -v vendor/ |xargs go vet
if ! type -f golint > /dev/null; then
go get -u github.com/golang/lint/golint
fi
go list ./... |grep -v vendor/ |xargs -L1 golint -set_exit_status
...@@ -26,7 +26,7 @@ type Config struct { ...@@ -26,7 +26,7 @@ type Config struct {
} }
// New creates a new Gitlab provider from a configuration. // New creates a new Gitlab provider from a configuration.
func New(c *config.Auth) (auth.Provider, error) { func New(c *config.Auth) (*Config, error) {
uw := make(map[string]bool) uw := make(map[string]bool)
for _, u := range c.UsersWhitelist { for _, u := range c.UsersWhitelist {
uw[u] = true uw[u] = true
......
...@@ -35,7 +35,7 @@ const Token = ` ...@@ -35,7 +35,7 @@ const Token = `
<h2>Access Token</h2> <h2>Access Token</h2>
</div> </div>
<div> <div>
<textarea style="font-size: 15pt" class="u-full-width code" readonly spellcheck="false" onclick="this.focus();this.select();">{{.Token}}</textarea> <textarea style="font-size: 12pt" class="u-full-width code" readonly spellcheck="false" onclick="this.focus();this.select();">{{.Token}}</textarea>
<h3> <h3>
The token will expire in &lt; 1 hour. The token will expire in &lt; 1 hour.
</h3> </h3>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment