-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit fdc02cd
Showing
14 changed files
with
1,368 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.DS_Store | ||
.idea | ||
.vscode | ||
|
||
/vault |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
GOARCH = amd64 | ||
|
||
UNAME = $(shell uname -s) | ||
|
||
ifndef OS | ||
ifeq ($(UNAME), Linux) | ||
OS = linux | ||
else ifeq ($(UNAME), Darwin) | ||
OS = darwin | ||
endif | ||
endif | ||
|
||
.DEFAULT_GOAL := all | ||
|
||
all: fmt build start | ||
|
||
build: | ||
mkdir -p vault/plugins | ||
GOOS=$(OS) GOARCH="$(GOARCH)" go build -o vault/plugins/vault-plugin-auth-ssh cmd/vault-plugin-auth-ssh/main.go | ||
|
||
start: | ||
vault server -dev -dev-root-token-id=root -dev-plugin-dir=./vault/plugins | ||
|
||
enable: | ||
vault auth enable -path=ssh vault-plugin-auth-ssh | ||
|
||
clean: | ||
rm -f ./vault/plugins/vault-plugin-auth-ssh | ||
|
||
fmt: | ||
go fmt $$(go list ./...) | ||
|
||
.PHONY: build clean fmt start enable |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
# Vault Plugin: SSH Auth Backend | ||
|
||
This is a standalone backend plugin for use with [Hashicorp Vault](https://www.github.com/hashicorp/vault). | ||
This plugin allows for SSH public keys and SSH certificates to authenticate with Vault. | ||
|
||
<!-- TOC --> | ||
|
||
- [Vault Plugin: SSH Auth Backend](#vault-plugin-ssh-auth-backend) | ||
- [Getting Started](#getting-started) | ||
- [Usage](#usage) | ||
- [Developing](#developing) | ||
- [Dev setup](#dev-setup) | ||
- [Using the plugin](#using-the-plugin) | ||
- [Global configuration](#global-configuration) | ||
- [Roles](#roles) | ||
- [SSH certificate](#ssh-certificate) | ||
- [SSH public keys](#ssh-public-keys) | ||
- [Logging in](#logging-in) | ||
- [SSH certificate](#ssh-certificate-1) | ||
- [SSH public key](#ssh-public-key) | ||
- [Creating signatures](#creating-signatures) | ||
|
||
<!-- /TOC --> | ||
|
||
## Getting Started | ||
|
||
This is a [Vault plugin](https://www.vaultproject.io/docs/internals/plugins.html) | ||
and is meant to work with Vault. This guide assumes you have already installed Vault | ||
and have a basic understanding of how Vault works. | ||
|
||
Otherwise, first read this guide on how to [get started with Vault](https://www.vaultproject.io/intro/getting-started/install.html). | ||
|
||
To learn specifically about how plugins work, see documentation on [Vault plugins](https://www.vaultproject.io/docs/internals/plugins.html). | ||
|
||
## Usage | ||
|
||
```sh | ||
$ vault auth enable -path=ssh vault-plugin-auth-ssh | ||
Success! Enabled vault-plugin-auth-ssh auth method at: ssh/ | ||
``` | ||
|
||
## Developing | ||
|
||
If you wish to work on this plugin, you'll first need | ||
[Go](https://www.golang.org) installed on your machine. | ||
|
||
Next, clone this repository into `vault-plugin-auth-ssh`. | ||
|
||
To compile a development version of this plugin, run `make build`. | ||
This will put the plugin binary in the `./vault/plugins` folders. | ||
|
||
Run `make start` to start a development version of vault with this plugin. | ||
|
||
Enable the auth plugin backend using the SSH auth plugin: | ||
|
||
```sh | ||
$ vault auth enable -path=ssh vault-plugin-auth-ssh | ||
Success! Enabled vault-plugin-auth-ssh auth method at: ssh/ | ||
``` | ||
|
||
### Dev setup | ||
|
||
Look into the `devsetup.sh` script, this will build the plugin, build certsig and setup a test environment with ssh-client signing, ssh certificate and public key test. | ||
|
||
## Using the plugin | ||
|
||
### Global configuration | ||
|
||
If you want to use ssh certificates you'll need to configure the ssh CA's which the certificates will validate against. | ||
|
||
sshca in this example is a file containing your SSH CA. You can specify multiple CA's. | ||
|
||
```sh | ||
$ vault write auth/ssh/config ssh_ca_public_keys=@sshca | ||
|
||
$ vault read auth/ssh/config | ||
Key Value | ||
--- ----- | ||
ssh_ca_public_keys [ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDrLFN/LCDOjPw327hWfHXMOk9+GmP+pOl2JEG7eSfkzwVhumDU12swjnPQ9H1tZVWzcfufTg+PgMd/hP19ADkRxQ2CTbz7YUPdD6LvJOCRK8TK+tKliaFL9/lWFtlitERyk91ZSqGbROjtCyGlnetxY1+tF5NqLFtQ1tsPrxjjdRQoUMHlF8yv/VUxMOCjAmuqxKrEl5mfZJcnYpnfEBgWoZNTKAXkp6KJWLAxyiHPVTt7azyMzivCTZc8eCKXIInRpOMR7TvHGxPG8tHn2XrI01ni9zXQ+xG1sqxecPBSWU8fekKxwg5bikrWw4/9kCNvxrwBpf1IzlIKhugig8MP3+Jlrjp5BFXFuaQatIk6zLMkzDpE/iZwDZv5qicXdLK/nbKHmGqFWupcvfHUe6rh16TOYFbpnRMOEvTYpR/PfLlnQKcbkQgbDR01N8DfLetxt635C+ANU4N1ebQqjKkwb8ZPr2ryF/Y8Z1PV0x5H25r8UZyoGAXIsP3zkP0Ev40Bx3umlU/jR8nF6QQmXdbs2McfZFO2g0VsXSzUOR0L5s5Sd/uoUCcpz9nmKlgRIqHIhVGF3+FjrIaj3tXT7ucyPAsVVk/l4yhMQSuNtFi0eqZRPcdMiKff5W9PfVyEkpXTcSFweGPdVehZxPnM7DfH7axpg73OLWxvwVzkah31WQ==] | ||
``` | ||
|
||
### Roles | ||
|
||
You can create / list / delete roles which are used to link your certificate or public keys to vault policies. | ||
|
||
#### SSH certificate | ||
|
||
Create a role with the policy `ssh-policy` bound to a certificate with the principal `ubuntu`. | ||
(prerequisite: a SSH CA needs to be configured in auth/ssh/config) | ||
|
||
```sh | ||
$ vault write auth/ssh/role/ubuntu token_policies="ssh-policy" principals="ubuntu" | ||
|
||
$ vault read auth/ssh/role/ubuntu | ||
Key Value | ||
--- ----- | ||
principals [ubuntu] | ||
public_keys <nil> | ||
token_bound_cidrs [] | ||
token_explicit_max_ttl 0s | ||
token_max_ttl 0s | ||
token_no_default_policy false | ||
token_num_uses 0 | ||
token_period 0s | ||
token_policies [ssh-policy] | ||
token_ttl 0s | ||
token_type default | ||
``` | ||
|
||
#### SSH public keys | ||
|
||
Create a role with the policy `ssh-policy` bound to a specific publickey. | ||
|
||
```sh | ||
$ vault write auth/ssh/role/ubuntu token_policies="ssh-policy" [email protected] | ||
|
||
$ vault read auth/ssh/role/ubuntu | ||
Key Value | ||
--- ----- | ||
principals <nil> | ||
public_keys [ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGg0xzFrvEYbZGkF5vWlHUutACUTLH7WMUG09NOi6skL] | ||
token_bound_cidrs [] | ||
token_explicit_max_ttl 0s | ||
token_max_ttl 0s | ||
token_no_default_policy false | ||
token_num_uses 0 | ||
token_period 0s | ||
token_policies [ssh-policy] | ||
token_ttl 0s | ||
token_type default | ||
``` | ||
|
||
### Logging in | ||
|
||
#### SSH certificate | ||
|
||
```sh | ||
vault write auth/ssh/login role=<role> cert=@<certfile> nonce=<base64encoded randomdata> signature=<base64encoded ssh signature over random data> | ||
``` | ||
|
||
For example | ||
|
||
```sh | ||
vault write auth/ssh/login role=ubuntu cert=@id_rsa-cert.pub signature=7ou2bupUMNmMqcorurOnbKnpbh9Kc7aBrF7nk6li0AhgnYAzhgfgGB3qJqI4qmf9TIc/x3JoNzo+Xq7KqXOXCA== nonce=AQAAAA7XdbPVKJn3uwA8 | ||
|
||
Key Value | ||
--- ----- | ||
token s.TpHP2eRCZNhuOENZUMas6YmV | ||
token_accessor 7FFAcAnxKOyM8BYWEN2KfYzR | ||
token_duration 768h | ||
token_renewable true | ||
token_policies ["default" "ssh-policy"] | ||
identity_policies [] | ||
policies ["default" "ssh-policy"] | ||
token_meta_role ubuntu | ||
``` | ||
|
||
#### SSH public key | ||
|
||
```sh | ||
vault write auth/ssh/login role=<role> public_key=@<publickey> nonce=<base64encoded randomdata> signature=<base64encoded ssh signature over random data> | ||
``` | ||
|
||
For example | ||
|
||
```sh | ||
$ vault write auth/ssh/login role=ubuntu public_key=@id_rsa.pub signature=fiEHdDHClYJIlRNWMC6c5QpM3ePi1xJh1KB90NI7CedZh0Siya5SG8ohy6zOk7e5l8Mdhx/FelykL43KH+OwBw== nonce=AQAAAA7XdbTAIytAhQA8 | ||
|
||
Key Value | ||
--- ----- | ||
token s.8L1uONTtaLHzZEtNw2oKmurk | ||
token_accessor SQ6jWOYKblSBFqywTezcdqVk | ||
token_duration 768h | ||
token_renewable true | ||
token_policies ["default" "ssh-policy"] | ||
identity_policies [] | ||
policies ["default" "ssh-policy"] | ||
token_meta_role ubuntu | ||
``` | ||
|
||
### Creating signatures | ||
|
||
For now you can use the [createsig](createsig/README.md) tool to generate your signature and nonce. | ||
|
||
```text | ||
This tool will print out a signature and nonce to be used with vault-plugin-auth-ssh | ||
Need createsig <key-path> <password> | ||
eg. createsig id_rsa mypassword | ||
If you don't have a password just omit it | ||
eg. createsig id_rsa | ||
``` | ||
|
||
For example: | ||
|
||
```sh | ||
$ vault write auth/ssh/login role=ubuntu public_key=@id_rsa.pub $(createsig id_rsa) | ||
``` | ||
|
||
```sh | ||
$ vault write auth/ssh/login role=ubuntu cert=@id_rsa-cert.pub $(createsig id_rsa) | ||
``` | ||
|
||
With a pass | ||
|
||
```sh | ||
$ vault write auth/ssh/login role=ubuntu public_key=@id_rsa.pub $(createsig id_rsa yourpass) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package sshauth | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/hashicorp/errwrap" | ||
"github.com/hashicorp/vault/sdk/framework" | ||
"github.com/hashicorp/vault/sdk/helper/tokenutil" | ||
"github.com/hashicorp/vault/sdk/logical" | ||
) | ||
|
||
const ( | ||
rolePrefix string = "role/" | ||
) | ||
|
||
// backend wraps the backend framework and adds a map for storing key value pairs. | ||
type backend struct { | ||
*framework.Backend | ||
} | ||
|
||
type ConfigEntry struct { | ||
tokenutil.TokenParams | ||
|
||
SSHCAPublicKeys []string `json:"ssh_ca_public_keys"` | ||
} | ||
|
||
var _ logical.Factory = Factory | ||
|
||
// Factory configures and returns Mock backends | ||
func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) { | ||
b := newBackend() | ||
|
||
if conf == nil { | ||
return nil, fmt.Errorf("configuration passed into backend is nil") | ||
} | ||
|
||
if err := b.Setup(ctx, conf); err != nil { | ||
return nil, err | ||
} | ||
|
||
return b, nil | ||
} | ||
|
||
func newBackend() *backend { | ||
b := &backend{} | ||
|
||
b.Backend = &framework.Backend{ | ||
Help: strings.TrimSpace(backendHelp), | ||
BackendType: logical.TypeCredential, | ||
AuthRenew: b.pathAuthRenew, | ||
PathsSpecial: &logical.Paths{ | ||
Unauthenticated: []string{ | ||
"login", | ||
}, | ||
SealWrapStorage: []string{ | ||
"config", | ||
}, | ||
}, | ||
Paths: framework.PathAppend( | ||
[]*framework.Path{ | ||
b.pathLogin(), | ||
b.pathConfig(), | ||
b.pathRoleList(), | ||
b.pathRole(), | ||
}, | ||
), | ||
} | ||
|
||
return b | ||
} | ||
|
||
func (b *backend) pathAuthRenew(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { | ||
roleName := req.Auth.InternalData["role"].(string) | ||
if roleName == "" { | ||
return nil, errors.New("failed to fetch role_name during renewal") | ||
} | ||
|
||
// Ensure that the Role still exists. | ||
role, err := b.role(ctx, req.Storage, roleName) | ||
if err != nil { | ||
return nil, errwrap.Wrapf(fmt.Sprintf("failed to validate role %s during renewal: {{err}}", roleName), err) | ||
} | ||
|
||
if role == nil { | ||
return nil, fmt.Errorf("role %s does not exist during renewal", roleName) | ||
} | ||
|
||
resp := &logical.Response{ | ||
Auth: req.Auth, | ||
} | ||
|
||
resp.Auth.TTL = role.TokenTTL | ||
resp.Auth.MaxTTL = role.TokenMaxTTL | ||
resp.Auth.Period = role.TokenPeriod | ||
|
||
return resp, nil | ||
} | ||
|
||
const ( | ||
backendHelp = ` | ||
The SSH backend plugin allows authentication using SSH certificates and public keys. | ||
` | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package main | ||
|
||
import ( | ||
"os" | ||
|
||
sshauth "github.com/42wim/vault-plugin-auth-ssh" | ||
"github.com/hashicorp/go-hclog" | ||
"github.com/hashicorp/vault/api" | ||
"github.com/hashicorp/vault/sdk/plugin" | ||
) | ||
|
||
func main() { | ||
apiClientMeta := &api.PluginAPIClientMeta{} | ||
flags := apiClientMeta.FlagSet() | ||
flags.Parse(os.Args[1:]) | ||
|
||
tlsConfig := apiClientMeta.GetTLSConfig() | ||
tlsProviderFunc := api.VaultPluginTLSProvider(tlsConfig) | ||
|
||
err := plugin.Serve(&plugin.ServeOpts{ | ||
BackendFactoryFunc: sshauth.Factory, | ||
TLSProviderFunc: tlsProviderFunc, | ||
}) | ||
if err != nil { | ||
logger := hclog.New(&hclog.LoggerOptions{}) | ||
|
||
logger.Error("plugin shutting down", "error", err) | ||
os.Exit(1) | ||
} | ||
} |
Oops, something went wrong.