azkeyvault

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 12, 2023 License: MIT Imports: 10 Imported by: 0

README

Signer and Decrypter for Azure KeyVault

This Go package wraps Azure KeyVault, sign and decrypt, into Golang crypto.Signer and crypto.Decrypter. The private key is protected by Azure KeyVault and no direct access from app.

Examples

HTTPS Server

SSH Client

Permissions required

Keep minimal permision to protect the private keys. No extra permission required if API is not in use.

  • Public() certificates/get
  • Signer.Sign() keys/sign
  • Decrypter.Decrypt() keys/decrypt

Documentation

Overview

Example (HttpsServer)
package main

import (
	"crypto/tls"
	"fmt"
	"log"
	"net"
	"net/http"

	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
	"github.com/Azure/azure-sdk-for-go/sdk/keyvault/azcertificates"
	"github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys"
	"github.com/tg123/azkeyvault"
)

func main() {
	// https server using azure keyvault
	vaultBaseURL := "https://<xxxx>.vault.azure.net/"
	keyName := "<key>"
	// config using client access key

	credential, err := azidentity.NewDefaultAzureCredential(nil)
	if err != nil {
		panic(err)
	}

	keyClient, err := azkeys.NewClient(vaultBaseURL, credential, nil)
	if err != nil {
		panic(err)
	}

	certClient, err := azcertificates.NewClient(vaultBaseURL, credential, nil)
	if err != nil {
		panic(err)
	}

	kv, err := azkeyvault.NewSigner(keyClient, certClient, keyName, "")
	if err != nil {
		panic(err)
	}

	l, err := net.Listen("tcp", ":9000")
	if err != nil {
		log.Fatal(err)
	}

	cert, err := kv.Certificate()
	if err != nil {
		log.Fatal(err)
	}

	tlsconf := &tls.Config{
		Certificates: []tls.Certificate{{
			Certificate: [][]byte{cert.Raw},
			PrivateKey:  kv,
		}},
	}

	netln := tls.NewListener(l, tlsconf)

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "hello\n")
	})

	panic(http.Serve(netln, nil))
}
Output:

Example (SshClient)
package main

import (
	"bytes"
	"fmt"
	"log"
	"strings"

	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
	"github.com/Azure/azure-sdk-for-go/sdk/keyvault/azcertificates"
	"github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys"
	"github.com/tg123/azkeyvault"
	"golang.org/x/crypto/ssh"
)

func main() {
	// config using client access key
	vaultBaseURL := "https://<xxxx>.vault.azure.net/"
	keyName := "<key>"

	credential, err := azidentity.NewDefaultAzureCredential(nil)
	if err != nil {
		panic(err)
	}

	keyClient, err := azkeys.NewClient(vaultBaseURL, credential, nil)
	if err != nil {
		panic(err)
	}

	certClient, err := azcertificates.NewClient(vaultBaseURL, credential, nil)
	if err != nil {
		panic(err)
	}

	kv, err := azkeyvault.NewSigner(keyClient, certClient, keyName, "")
	if err != nil {
		panic(err)
	}

	signer, err := ssh.NewSignerFromSigner(kv)
	if err != nil {
		panic(err)
	}

	fmt.Printf(`echo "%s" >> /root/.ssh/authorized_keys`, strings.Trim(string(ssh.MarshalAuthorizedKey(signer.PublicKey())), "\n"))
	fmt.Println()

	client, err := ssh.Dial("tcp", "127.0.0.1:22", &ssh.ClientConfig{
		User: "root",
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(signer),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	})
	if err != nil {
		log.Fatal("Failed to dial: ", err)
	}
	defer client.Close()

	// Each ClientConn can support multiple interactive sessions,
	// represented by a Session.
	session, err := client.NewSession()
	if err != nil {
		log.Fatal("Failed to create session: ", err)
	}
	defer session.Close()

	// Once a Session is created, you can execute a single command on
	// the remote side using the Run method.
	var b bytes.Buffer
	session.Stdout = &b
	if err := session.Run("/usr/bin/whoami"); err != nil {
		log.Fatal("Failed to run: " + err.Error())
	}
	fmt.Println(b.String())
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrUnsupportedHash is returned by Signer.Sign() when the provided hash
	// algorithm isn't supported.
	ErrUnsupportedHash = fmt.Errorf("unsupported hash algorithm")
)

Functions

This section is empty.

Types

type Decrypter

type Decrypter interface {
	crypto.Decrypter

	// Certificate return x509 certificate of Decrypter
	Certificate() (*x509.Certificate, error)
}

func NewDecrypter

func NewDecrypter(
	keyVaultClient *azkeys.Client,
	certClient *azcertificates.Client,
	keyName string,
	keyVersion string,
) (Decrypter, error)

type DecrypterOpts

type DecrypterOpts struct {
	Algorithm azkeys.JSONWebKeyEncryptionAlgorithm
	Context   context.Context
}

type Signer

type Signer interface {
	crypto.Signer

	// Certificate return x509 certificate of Signer
	Certificate() (*x509.Certificate, error)
}

func NewSigner

func NewSigner(
	keyClient *azkeys.Client,
	certClient *azcertificates.Client,
	keyName string,
	keyVersion string,
) (Signer, error)

type SignerOpts

type SignerOpts struct {
	Algorithm azkeys.JSONWebKeySignatureAlgorithm
	Context   context.Context
}

func (*SignerOpts) HashFunc

func (o *SignerOpts) HashFunc() crypto.Hash

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL