Skip to content

Commit

Permalink
use approle for auth
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucretius committed Apr 30, 2020
1 parent c4c4ed6 commit e6bcdf5
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 20 deletions.
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ Another way to do this, which would allow us to run the snapshot agent anywhere,

`timeout` How often to run the snapshot agent. Examples: `30s`, `1h`. See https://golang.org/pkg/time/#ParseDuration for a full list of valid time units.

`token` Specify the token used to call the Vault API. This can also be specified via the env variable `SNAPSHOT_TOKEN`.
`role_id` Specifies the role_id used to call the Vault API. See the authentication steps below.

`secret_id` Specifies the secret_id used to call the Vault API.

### Storage options

Expand Down Expand Up @@ -65,3 +67,32 @@ Note that if you specify more than one storage option, *all* options will be wri
`account_key` - The account key of the storage account

`container_name` The name of the blob container to write to


## Authentication

You must do some quick initial setup prior to being able to use the Snapshot Agent. This involves the following:

`vault login` with an admin user.
Create the following policy `vault policy write snapshot ./my_policies/snapshot_policy.hcl`
where `snapshot_policy.hcl` is:

```hcl
path "/sys/storage/raft/snapshot"
{
capabilities = ["read"]
}
```

Then run:
```
vault write auth/approle/role/snapshot token_policies="snapshot"
vault read auth/approle/role/snapshot/role-id
vault write -f auth/approle/role/snapshot/secret-id
```

and copy your secret and role ids, and place them into the snapshot file. The snapshot agent will use them to request client tokens, so that it can interact with your Vault cluster. The above policy is the minimum required policy to be able to generate snapshots. The snapshot agent will automatically renew the token when it is going to expire.

The AppRole allows the snapshot agent to automatically rotate tokens to avoid long-lived credentials.

To learn more about AppRole's and why this project chose to use them, see [the Vault docs](https://www.vaultproject.io/docs/auth/approle)
17 changes: 9 additions & 8 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import (

// Configuration is the overall config object
type Configuration struct {
Address string `json:"addr"`
Retain int64 `json:"retain"`
Timeout string `json:"freq"`
AWS S3Config `json:"aws_storage"`
Local LocalConfig `json:"local_storage"`
GCP GCPConfig `json:"google_storage"`
Azure AzureConfig `json:"azure_blob_storage"`
Token string `json:"token"`
Address string `json:"addr"`
Retain int64 `json:"retain"`
Timeout string `json:"freq"`
AWS S3Config `json:"aws_storage"`
Local LocalConfig `json:"local_storage"`
GCP GCPConfig `json:"google_storage"`
Azure AzureConfig `json:"azure_blob_storage"`
RoleID string `json:"role_id"`
SecretID string `json:"secret_id"`
}

// AzureConfig is the configuration for Azure blob snapshots
Expand Down
4 changes: 3 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ func main() {
log.Fatalln("Error retrieving Current instance IP. Verify internet connectivity.")
}
for {
if snapshotter.TokenExpiration.Before(time.Now()) {
snapshotter.SetClientTokenFromAppRole(c)
}
leader, err := snapshotter.API.Sys().Leader()
if err != nil {
log.Println(err.Error())
Expand Down Expand Up @@ -112,6 +115,5 @@ func getInstanceIP() (string, error) {
defer conn.Close()

localAddr := conn.LocalAddr().(*net.UDPAddr)
log.Println(localAddr.IP.String())
return localAddr.IP.String(), nil
}
32 changes: 22 additions & 10 deletions snapshot_agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"log"
"net/url"
"os"
"time"

"cloud.google.com/go/storage"
"github.com/Azure/azure-storage-blob-go/azblob"
Expand All @@ -20,11 +21,12 @@ import (
)

type Snapshotter struct {
API *vaultApi.Client
Uploader *s3manager.Uploader
S3Client *s3.S3
GCPBucket *storage.BucketHandle
AzureUploader azblob.ContainerURL
API *vaultApi.Client
Uploader *s3manager.Uploader
S3Client *s3.S3
GCPBucket *storage.BucketHandle
AzureUploader azblob.ContainerURL
TokenExpiration time.Time
}

func NewSnapshotter(config *config.Configuration) (*Snapshotter, error) {
Expand All @@ -50,10 +52,6 @@ func NewSnapshotter(config *config.Configuration) (*Snapshotter, error) {

func (s *Snapshotter) ConfigureVaultClient(config *config.Configuration) error {
vaultConfig := vaultApi.DefaultConfig()
tokenEnvVar := os.Getenv("SNAPSHOT_TOKEN")
if tokenEnvVar != "" {
config.Token = tokenEnvVar
}
vaultConfig.Address = config.Address
tlsConfig := &vaultApi.TLSConfig{
Insecure: true,
Expand All @@ -63,8 +61,22 @@ func (s *Snapshotter) ConfigureVaultClient(config *config.Configuration) error {
if err != nil {
return err
}
api.SetToken(config.Token)
s.API = api
s.SetClientTokenFromAppRole(config)
return nil
}

func (s *Snapshotter) SetClientTokenFromAppRole(config *config.Configuration) error {
data := map[string]interface{}{
"role_id": config.RoleID,
"secret_id": config.SecretID,
}
resp, err := s.API.Logical().Write("auth/approle/login", data)
if err != nil {
return fmt.Errorf("error logging into AppRole auth backend: %s", err)
}
s.API.SetToken(resp.Auth.ClientToken)
s.TokenExpiration = time.Now().Add(time.Duration((time.Second * time.Duration(resp.Auth.LeaseDuration)) / 2))
return nil
}

Expand Down

0 comments on commit e6bcdf5

Please sign in to comment.